@domternal/extension-mention 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/index.cjs +445 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +181 -0
- package/dist/index.d.ts +181 -0
- package/dist/index.js +438 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { CommandSpec, Node } from '@domternal/core';
|
|
2
|
+
import { NodeType, Node as Node$1, DOMOutputSpec } from '@domternal/pm/model';
|
|
3
|
+
import { EditorState, Plugin } from '@domternal/pm/state';
|
|
4
|
+
import { EditorView } from '@domternal/pm/view';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Mention Suggestion Plugin
|
|
8
|
+
*
|
|
9
|
+
* Headless ProseMirror plugin that watches for trigger characters (e.g. '@', '#'),
|
|
10
|
+
* tracks the query, supports async item fetching with debounce, and calls render
|
|
11
|
+
* callbacks so framework wrappers can display a dropdown picker.
|
|
12
|
+
*
|
|
13
|
+
* Adapted from the emoji suggestion plugin with additions:
|
|
14
|
+
* - Async items support with 150ms debounce
|
|
15
|
+
* - Multiple plugin instances (one per trigger, unique PluginKey)
|
|
16
|
+
* - Inline decoration on active trigger+query range
|
|
17
|
+
* - invalidNodes context check
|
|
18
|
+
* - appendText after insertion
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** A single mention item returned by the items() callback. */
|
|
22
|
+
interface MentionItem {
|
|
23
|
+
/** Unique identifier (e.g., user ID, tag slug). */
|
|
24
|
+
id: string;
|
|
25
|
+
/** Display text (e.g., "John Doe", "feature-request"). */
|
|
26
|
+
label: string;
|
|
27
|
+
/** Allow extra data (avatar URL, email, role, etc.). */
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/** Configuration for a single mention trigger. */
|
|
31
|
+
interface MentionTrigger {
|
|
32
|
+
/** Trigger character. Default: '@' */
|
|
33
|
+
char: string;
|
|
34
|
+
/** Unique name for this trigger type (e.g., 'user', 'tag'). */
|
|
35
|
+
name: string;
|
|
36
|
+
/** Fetch items matching a query. Supports sync and async (Promise). */
|
|
37
|
+
items: (props: {
|
|
38
|
+
query: string;
|
|
39
|
+
trigger: MentionTrigger;
|
|
40
|
+
}) => MentionItem[] | Promise<MentionItem[]>;
|
|
41
|
+
/** Render callbacks for the suggestion popup. */
|
|
42
|
+
render?: () => MentionSuggestionRenderer;
|
|
43
|
+
/** Minimum query length before showing suggestions. Default: 0 */
|
|
44
|
+
minQueryLength?: number;
|
|
45
|
+
/** Allow spaces in query. Default: false */
|
|
46
|
+
allowSpaces?: boolean;
|
|
47
|
+
/** Text to append after mention insertion. Default: ' ' (space) */
|
|
48
|
+
appendText?: string;
|
|
49
|
+
/** Node types where suggestion should NOT activate (e.g. ['codeBlock']). Default: [] */
|
|
50
|
+
invalidNodes?: string[];
|
|
51
|
+
/** Debounce delay in ms for items() calls. Use >0 for async/API-backed items. Default: 0 (immediate) */
|
|
52
|
+
debounce?: number;
|
|
53
|
+
/** CSS class for the inline decoration on the active trigger+query range. Default: 'mention-suggestion' */
|
|
54
|
+
decorationClass?: string;
|
|
55
|
+
/** HTML tag for the inline decoration element. Default: 'span' */
|
|
56
|
+
decorationTag?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Controls whether the suggestion should be shown. Return `false` to suppress.
|
|
59
|
+
* Useful for collaboration (suppress suggestions triggered by remote cursors)
|
|
60
|
+
* or any custom logic based on editor state.
|
|
61
|
+
*/
|
|
62
|
+
shouldShow?: (props: {
|
|
63
|
+
state: EditorState;
|
|
64
|
+
view: EditorView;
|
|
65
|
+
}) => boolean;
|
|
66
|
+
}
|
|
67
|
+
/** Props passed to suggestion renderer callbacks. */
|
|
68
|
+
interface MentionSuggestionProps {
|
|
69
|
+
/** Current query string (text after trigger char). */
|
|
70
|
+
query: string;
|
|
71
|
+
/** Document range of the trigger + query (for replacement). */
|
|
72
|
+
range: {
|
|
73
|
+
from: number;
|
|
74
|
+
to: number;
|
|
75
|
+
};
|
|
76
|
+
/** Filtered mention items matching the query. */
|
|
77
|
+
items: MentionItem[];
|
|
78
|
+
/** Call to insert a mention and close the suggestion. */
|
|
79
|
+
command: (item: MentionItem) => void;
|
|
80
|
+
/** Returns the client rect of the cursor for positioning the popup. */
|
|
81
|
+
clientRect: (() => DOMRect | null) | null;
|
|
82
|
+
}
|
|
83
|
+
/** Render callbacks for the suggestion popup. */
|
|
84
|
+
interface MentionSuggestionRenderer {
|
|
85
|
+
/** Called when suggestion is first activated. */
|
|
86
|
+
onStart: (props: MentionSuggestionProps) => void;
|
|
87
|
+
/** Called when query or items change. */
|
|
88
|
+
onUpdate: (props: MentionSuggestionProps) => void;
|
|
89
|
+
/** Called when suggestion is deactivated. */
|
|
90
|
+
onExit: () => void;
|
|
91
|
+
/** Called on keydown — return true to prevent default editor handling. */
|
|
92
|
+
onKeyDown: (event: KeyboardEvent) => boolean;
|
|
93
|
+
}
|
|
94
|
+
interface SuggestionPluginOptions {
|
|
95
|
+
trigger: MentionTrigger;
|
|
96
|
+
nodeType: NodeType | null;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Creates a ProseMirror plugin for mention suggestion/autocomplete.
|
|
100
|
+
* One plugin instance per trigger.
|
|
101
|
+
*/
|
|
102
|
+
declare function createMentionSuggestionPlugin(options: SuggestionPluginOptions): Plugin;
|
|
103
|
+
/**
|
|
104
|
+
* Programmatically dismiss the mention suggestion for a given trigger.
|
|
105
|
+
* Dispatches a meta transaction to reset the plugin state.
|
|
106
|
+
*/
|
|
107
|
+
declare function dismissMentionSuggestion(view: EditorView, triggerName: string): void;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Mention Node Extension
|
|
111
|
+
*
|
|
112
|
+
* Inline atom node for @mentions with multi-trigger support,
|
|
113
|
+
* headless suggestion plugin, async item fetching, and configurable rendering.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* import { Mention } from '@domternal/extension-mention';
|
|
118
|
+
*
|
|
119
|
+
* const editor = new Editor({
|
|
120
|
+
* extensions: [
|
|
121
|
+
* Mention.configure({
|
|
122
|
+
* suggestion: {
|
|
123
|
+
* char: '@',
|
|
124
|
+
* name: 'user',
|
|
125
|
+
* items: ({ query }) => users.filter(u => u.label.includes(query)),
|
|
126
|
+
* render: createMentionRenderer,
|
|
127
|
+
* },
|
|
128
|
+
* }),
|
|
129
|
+
* ],
|
|
130
|
+
* });
|
|
131
|
+
*
|
|
132
|
+
* // Insert mention programmatically
|
|
133
|
+
* editor.commands.insertMention({ id: '1', label: 'Alice' });
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
declare module '@domternal/core' {
|
|
138
|
+
interface RawCommands {
|
|
139
|
+
insertMention: CommandSpec<[attrs: {
|
|
140
|
+
id: string;
|
|
141
|
+
label: string;
|
|
142
|
+
type?: string;
|
|
143
|
+
}]>;
|
|
144
|
+
deleteMention: CommandSpec<[id?: string]>;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
interface MentionOptions {
|
|
148
|
+
/** Single trigger config (shorthand). Ignored if `triggers` is non-empty. */
|
|
149
|
+
suggestion: MentionTrigger | null;
|
|
150
|
+
/** Multiple trigger configs. Takes precedence over `suggestion`. */
|
|
151
|
+
triggers: MentionTrigger[];
|
|
152
|
+
/** Delete trigger char alongside mention on Backspace. Default: false */
|
|
153
|
+
deleteTriggerWithBackspace: boolean;
|
|
154
|
+
/** Custom render for HTML output (e.g. render as <a>). */
|
|
155
|
+
renderHTML: ((props: {
|
|
156
|
+
node: Node$1;
|
|
157
|
+
options: MentionOptions;
|
|
158
|
+
HTMLAttributes: Record<string, unknown>;
|
|
159
|
+
}) => DOMOutputSpec) | null;
|
|
160
|
+
/** Custom render for plain text output. */
|
|
161
|
+
renderText: ((props: {
|
|
162
|
+
node: Node$1;
|
|
163
|
+
options: MentionOptions;
|
|
164
|
+
}) => string) | null;
|
|
165
|
+
/** HTML attributes for the mention element. */
|
|
166
|
+
HTMLAttributes: Record<string, unknown>;
|
|
167
|
+
}
|
|
168
|
+
interface MentionStorage {
|
|
169
|
+
/** Find all mention nodes in the document. */
|
|
170
|
+
findMentions: () => {
|
|
171
|
+
id: string;
|
|
172
|
+
label: string;
|
|
173
|
+
type: string;
|
|
174
|
+
pos: number;
|
|
175
|
+
}[];
|
|
176
|
+
/** @internal Trigger name → char lookup map. */
|
|
177
|
+
_triggerCharMap: Map<string, string>;
|
|
178
|
+
}
|
|
179
|
+
declare const Mention: Node<MentionOptions, MentionStorage>;
|
|
180
|
+
|
|
181
|
+
export { Mention, type MentionItem, type MentionOptions, type MentionStorage, type MentionSuggestionProps, type MentionSuggestionRenderer, type MentionTrigger, createMentionSuggestionPlugin, Mention as default, dismissMentionSuggestion };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { CommandSpec, Node } from '@domternal/core';
|
|
2
|
+
import { NodeType, Node as Node$1, DOMOutputSpec } from '@domternal/pm/model';
|
|
3
|
+
import { EditorState, Plugin } from '@domternal/pm/state';
|
|
4
|
+
import { EditorView } from '@domternal/pm/view';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Mention Suggestion Plugin
|
|
8
|
+
*
|
|
9
|
+
* Headless ProseMirror plugin that watches for trigger characters (e.g. '@', '#'),
|
|
10
|
+
* tracks the query, supports async item fetching with debounce, and calls render
|
|
11
|
+
* callbacks so framework wrappers can display a dropdown picker.
|
|
12
|
+
*
|
|
13
|
+
* Adapted from the emoji suggestion plugin with additions:
|
|
14
|
+
* - Async items support with 150ms debounce
|
|
15
|
+
* - Multiple plugin instances (one per trigger, unique PluginKey)
|
|
16
|
+
* - Inline decoration on active trigger+query range
|
|
17
|
+
* - invalidNodes context check
|
|
18
|
+
* - appendText after insertion
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** A single mention item returned by the items() callback. */
|
|
22
|
+
interface MentionItem {
|
|
23
|
+
/** Unique identifier (e.g., user ID, tag slug). */
|
|
24
|
+
id: string;
|
|
25
|
+
/** Display text (e.g., "John Doe", "feature-request"). */
|
|
26
|
+
label: string;
|
|
27
|
+
/** Allow extra data (avatar URL, email, role, etc.). */
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/** Configuration for a single mention trigger. */
|
|
31
|
+
interface MentionTrigger {
|
|
32
|
+
/** Trigger character. Default: '@' */
|
|
33
|
+
char: string;
|
|
34
|
+
/** Unique name for this trigger type (e.g., 'user', 'tag'). */
|
|
35
|
+
name: string;
|
|
36
|
+
/** Fetch items matching a query. Supports sync and async (Promise). */
|
|
37
|
+
items: (props: {
|
|
38
|
+
query: string;
|
|
39
|
+
trigger: MentionTrigger;
|
|
40
|
+
}) => MentionItem[] | Promise<MentionItem[]>;
|
|
41
|
+
/** Render callbacks for the suggestion popup. */
|
|
42
|
+
render?: () => MentionSuggestionRenderer;
|
|
43
|
+
/** Minimum query length before showing suggestions. Default: 0 */
|
|
44
|
+
minQueryLength?: number;
|
|
45
|
+
/** Allow spaces in query. Default: false */
|
|
46
|
+
allowSpaces?: boolean;
|
|
47
|
+
/** Text to append after mention insertion. Default: ' ' (space) */
|
|
48
|
+
appendText?: string;
|
|
49
|
+
/** Node types where suggestion should NOT activate (e.g. ['codeBlock']). Default: [] */
|
|
50
|
+
invalidNodes?: string[];
|
|
51
|
+
/** Debounce delay in ms for items() calls. Use >0 for async/API-backed items. Default: 0 (immediate) */
|
|
52
|
+
debounce?: number;
|
|
53
|
+
/** CSS class for the inline decoration on the active trigger+query range. Default: 'mention-suggestion' */
|
|
54
|
+
decorationClass?: string;
|
|
55
|
+
/** HTML tag for the inline decoration element. Default: 'span' */
|
|
56
|
+
decorationTag?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Controls whether the suggestion should be shown. Return `false` to suppress.
|
|
59
|
+
* Useful for collaboration (suppress suggestions triggered by remote cursors)
|
|
60
|
+
* or any custom logic based on editor state.
|
|
61
|
+
*/
|
|
62
|
+
shouldShow?: (props: {
|
|
63
|
+
state: EditorState;
|
|
64
|
+
view: EditorView;
|
|
65
|
+
}) => boolean;
|
|
66
|
+
}
|
|
67
|
+
/** Props passed to suggestion renderer callbacks. */
|
|
68
|
+
interface MentionSuggestionProps {
|
|
69
|
+
/** Current query string (text after trigger char). */
|
|
70
|
+
query: string;
|
|
71
|
+
/** Document range of the trigger + query (for replacement). */
|
|
72
|
+
range: {
|
|
73
|
+
from: number;
|
|
74
|
+
to: number;
|
|
75
|
+
};
|
|
76
|
+
/** Filtered mention items matching the query. */
|
|
77
|
+
items: MentionItem[];
|
|
78
|
+
/** Call to insert a mention and close the suggestion. */
|
|
79
|
+
command: (item: MentionItem) => void;
|
|
80
|
+
/** Returns the client rect of the cursor for positioning the popup. */
|
|
81
|
+
clientRect: (() => DOMRect | null) | null;
|
|
82
|
+
}
|
|
83
|
+
/** Render callbacks for the suggestion popup. */
|
|
84
|
+
interface MentionSuggestionRenderer {
|
|
85
|
+
/** Called when suggestion is first activated. */
|
|
86
|
+
onStart: (props: MentionSuggestionProps) => void;
|
|
87
|
+
/** Called when query or items change. */
|
|
88
|
+
onUpdate: (props: MentionSuggestionProps) => void;
|
|
89
|
+
/** Called when suggestion is deactivated. */
|
|
90
|
+
onExit: () => void;
|
|
91
|
+
/** Called on keydown — return true to prevent default editor handling. */
|
|
92
|
+
onKeyDown: (event: KeyboardEvent) => boolean;
|
|
93
|
+
}
|
|
94
|
+
interface SuggestionPluginOptions {
|
|
95
|
+
trigger: MentionTrigger;
|
|
96
|
+
nodeType: NodeType | null;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Creates a ProseMirror plugin for mention suggestion/autocomplete.
|
|
100
|
+
* One plugin instance per trigger.
|
|
101
|
+
*/
|
|
102
|
+
declare function createMentionSuggestionPlugin(options: SuggestionPluginOptions): Plugin;
|
|
103
|
+
/**
|
|
104
|
+
* Programmatically dismiss the mention suggestion for a given trigger.
|
|
105
|
+
* Dispatches a meta transaction to reset the plugin state.
|
|
106
|
+
*/
|
|
107
|
+
declare function dismissMentionSuggestion(view: EditorView, triggerName: string): void;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Mention Node Extension
|
|
111
|
+
*
|
|
112
|
+
* Inline atom node for @mentions with multi-trigger support,
|
|
113
|
+
* headless suggestion plugin, async item fetching, and configurable rendering.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* import { Mention } from '@domternal/extension-mention';
|
|
118
|
+
*
|
|
119
|
+
* const editor = new Editor({
|
|
120
|
+
* extensions: [
|
|
121
|
+
* Mention.configure({
|
|
122
|
+
* suggestion: {
|
|
123
|
+
* char: '@',
|
|
124
|
+
* name: 'user',
|
|
125
|
+
* items: ({ query }) => users.filter(u => u.label.includes(query)),
|
|
126
|
+
* render: createMentionRenderer,
|
|
127
|
+
* },
|
|
128
|
+
* }),
|
|
129
|
+
* ],
|
|
130
|
+
* });
|
|
131
|
+
*
|
|
132
|
+
* // Insert mention programmatically
|
|
133
|
+
* editor.commands.insertMention({ id: '1', label: 'Alice' });
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
declare module '@domternal/core' {
|
|
138
|
+
interface RawCommands {
|
|
139
|
+
insertMention: CommandSpec<[attrs: {
|
|
140
|
+
id: string;
|
|
141
|
+
label: string;
|
|
142
|
+
type?: string;
|
|
143
|
+
}]>;
|
|
144
|
+
deleteMention: CommandSpec<[id?: string]>;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
interface MentionOptions {
|
|
148
|
+
/** Single trigger config (shorthand). Ignored if `triggers` is non-empty. */
|
|
149
|
+
suggestion: MentionTrigger | null;
|
|
150
|
+
/** Multiple trigger configs. Takes precedence over `suggestion`. */
|
|
151
|
+
triggers: MentionTrigger[];
|
|
152
|
+
/** Delete trigger char alongside mention on Backspace. Default: false */
|
|
153
|
+
deleteTriggerWithBackspace: boolean;
|
|
154
|
+
/** Custom render for HTML output (e.g. render as <a>). */
|
|
155
|
+
renderHTML: ((props: {
|
|
156
|
+
node: Node$1;
|
|
157
|
+
options: MentionOptions;
|
|
158
|
+
HTMLAttributes: Record<string, unknown>;
|
|
159
|
+
}) => DOMOutputSpec) | null;
|
|
160
|
+
/** Custom render for plain text output. */
|
|
161
|
+
renderText: ((props: {
|
|
162
|
+
node: Node$1;
|
|
163
|
+
options: MentionOptions;
|
|
164
|
+
}) => string) | null;
|
|
165
|
+
/** HTML attributes for the mention element. */
|
|
166
|
+
HTMLAttributes: Record<string, unknown>;
|
|
167
|
+
}
|
|
168
|
+
interface MentionStorage {
|
|
169
|
+
/** Find all mention nodes in the document. */
|
|
170
|
+
findMentions: () => {
|
|
171
|
+
id: string;
|
|
172
|
+
label: string;
|
|
173
|
+
type: string;
|
|
174
|
+
pos: number;
|
|
175
|
+
}[];
|
|
176
|
+
/** @internal Trigger name → char lookup map. */
|
|
177
|
+
_triggerCharMap: Map<string, string>;
|
|
178
|
+
}
|
|
179
|
+
declare const Mention: Node<MentionOptions, MentionStorage>;
|
|
180
|
+
|
|
181
|
+
export { Mention, type MentionItem, type MentionOptions, type MentionStorage, type MentionSuggestionProps, type MentionSuggestionRenderer, type MentionTrigger, createMentionSuggestionPlugin, Mention as default, dismissMentionSuggestion };
|