Skip to content

Commit 572aed7

Browse files
committed
feat: add basic mentions menu example
1 parent 51838a8 commit 572aed7

File tree

7 files changed

+367
-30
lines changed

7 files changed

+367
-30
lines changed

docs/src/app/app.routes.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { RemovingDefaultBlocksPage } from '../pages/examples/basic/removing-defa
99
import { SelectionBlocksPage } from '../pages/examples/basic/selection-blocks/selection-blocks.page';
1010
import { AlertBlockPage } from '../pages/examples/custom/alert-block/alert-block.page';
1111
import { ApiContentBlockPage } from '../pages/examples/custom/api-content-block/api-content-block.page';
12+
import { MentionsMenuPage } from '../pages/examples/custom/mentions-menu/mentions-menu.page';
1213
import { ExamplesPage } from '../pages/examples/examples.page';
1314
import { ConvertToHtmlPage } from '../pages/examples/interoperability/convert-to-html/convert-to-html.page';
1415
import { AddingSideMenuDragHandleItemsPage } from '../pages/examples/ui-components/adding-side-menu-drag-handle-items/adding-side-menu-drag-handle-items.page';
@@ -52,6 +53,10 @@ export const appRoutes: Route[] = [
5253
path: 'custom/api-content-block',
5354
component: ApiContentBlockPage,
5455
},
56+
{
57+
path: 'custom/mentions-menu',
58+
component: MentionsMenuPage,
59+
},
5560
{
5661
path: 'interoperability/convert-to-html',
5762
component: ConvertToHtmlPage,
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
import { CommonModule } from '@angular/common';
2+
import { Component } from '@angular/core';
3+
import {
4+
BlockNoteEditor,
5+
BlockNoteSchema,
6+
defaultBlockSpecs,
7+
defaultInlineContentSpecs,
8+
defaultStyleSpecs,
9+
PartialBlock,
10+
} from '@blocknote/core';
11+
import {
12+
BlockNoteEditorOptionsType,
13+
BnaEditorComponent,
14+
BnaSuggestionsMenuComponent,
15+
BnaSuggestionsMenuControllerDirective,
16+
HlmButtonDirective,
17+
} from '@dytab/block-note-angular';
18+
import { Mention } from './mentions';
19+
20+
const getMentionMenuItems = (editor: typeof schema.BlockNoteEditor) => {
21+
const users = ['Steve', 'Bob', 'Joe', 'Mike'];
22+
23+
return users.map((user) => ({
24+
title: user,
25+
onItemClick: () => {
26+
editor.insertInlineContent([
27+
{
28+
type: 'mention',
29+
props: {
30+
user,
31+
},
32+
},
33+
' ', // add a space after the mention
34+
]);
35+
},
36+
}));
37+
};
38+
const schema = BlockNoteSchema.create({
39+
blockSpecs: {
40+
...defaultBlockSpecs,
41+
},
42+
inlineContentSpecs: { ...defaultInlineContentSpecs, mention: Mention },
43+
styleSpecs: { ...defaultStyleSpecs },
44+
});
45+
@Component({
46+
selector: 'bna-mentions-menu-example',
47+
standalone: true,
48+
imports: [
49+
CommonModule,
50+
BnaEditorComponent,
51+
HlmButtonDirective,
52+
BnaSuggestionsMenuControllerDirective,
53+
BnaSuggestionsMenuComponent,
54+
],
55+
template: `<bna-editor
56+
[initialContent]="initialContent"
57+
[options]="options"
58+
(onEditorReady)="onEditorReady($event)"
59+
><bna-suggestions-menu-controller triggerCharacter="@">
60+
<div
61+
class="bg-background shadow-2xl shadow-neutral-500 rounded p-1 flex flex-col"
62+
>
63+
@for(item of items;track item.title){
64+
<button
65+
hlmBtn
66+
variant="ghost"
67+
size="sm"
68+
(mousedown)="item.onItemClick()"
69+
>
70+
{{ item.title }}
71+
</button>
72+
}
73+
</div>
74+
</bna-suggestions-menu-controller></bna-editor
75+
>`,
76+
})
77+
export class MentionsMenuExample {
78+
items: { title: string; onItemClick: () => void }[] = [];
79+
initialContent: PartialBlock<
80+
typeof schema.blockSchema,
81+
typeof schema.inlineContentSchema
82+
>[] = [
83+
{
84+
type: 'paragraph',
85+
content: 'Welcome to this demo!',
86+
},
87+
{
88+
type: 'paragraph',
89+
content: [
90+
{
91+
type: 'mention',
92+
props: {
93+
user: 'Steve',
94+
},
95+
},
96+
{
97+
type: 'text',
98+
text: ' <- This is an example mention',
99+
styles: {},
100+
},
101+
],
102+
},
103+
{
104+
type: 'paragraph',
105+
content: "Press the '@' key to open the mentions menu and add another",
106+
},
107+
{
108+
type: 'paragraph',
109+
},
110+
];
111+
options: BlockNoteEditorOptionsType = { schema };
112+
113+
onEditorReady($event: BlockNoteEditor<any, any, any>) {
114+
this.items = getMentionMenuItems($event);
115+
}
116+
}
117+
118+
export const mentionsMenuExampleCode = `import { CommonModule } from '@angular/common';
119+
import { Component } from '@angular/core';
120+
import {
121+
BlockNoteEditor,
122+
BlockNoteSchema,
123+
defaultBlockSpecs,
124+
defaultInlineContentSpecs,
125+
defaultStyleSpecs,
126+
PartialBlock,
127+
} from '@blocknote/core';
128+
import {
129+
BlockNoteEditorOptionsType,
130+
BnaEditorComponent,
131+
BnaSuggestionsMenuComponent,
132+
BnaSuggestionsMenuControllerDirective,
133+
HlmButtonDirective,
134+
} from '@dytab/block-note-angular';
135+
import { Mention } from './mentions';
136+
137+
const getMentionMenuItems = (editor: typeof schema.BlockNoteEditor) => {
138+
const users = ['Steve', 'Bob', 'Joe', 'Mike'];
139+
140+
return users.map((user) => ({
141+
title: user,
142+
onItemClick: () => {
143+
editor.insertInlineContent([
144+
{
145+
type: 'mention',
146+
props: {
147+
user,
148+
},
149+
},
150+
' ', // add a space after the mention
151+
]);
152+
},
153+
}));
154+
};
155+
const schema = BlockNoteSchema.create({
156+
blockSpecs: {
157+
...defaultBlockSpecs,
158+
},
159+
inlineContentSpecs: { ...defaultInlineContentSpecs, mention: Mention },
160+
styleSpecs: { ...defaultStyleSpecs },
161+
});
162+
@Component({
163+
selector: 'bna-mentions-menu-example',
164+
standalone: true,
165+
imports: [
166+
CommonModule,
167+
BnaEditorComponent,
168+
HlmButtonDirective,
169+
BnaSuggestionsMenuControllerDirective,
170+
BnaSuggestionsMenuComponent,
171+
],
172+
template: \`<bna-editor
173+
[initialContent]="initialContent"
174+
[options]="options"
175+
(onEditorReady)="onEditorReady($event)"
176+
><bna-suggestions-menu-controller triggerCharacter="@">
177+
<div
178+
class="bg-background shadow-2xl shadow-neutral-500 rounded p-1 flex flex-col"
179+
>
180+
@for(item of items;track item.title){
181+
<button
182+
hlmBtn
183+
variant="ghost"
184+
size="sm"
185+
(mousedown)="item.onItemClick()"
186+
>
187+
{{ item.title }}
188+
</button>
189+
}
190+
</div>
191+
</bna-suggestions-menu-controller></bna-editor
192+
>\`,
193+
})
194+
export class MentionsMenuExample {
195+
items: { title: string; onItemClick: () => void }[] = [];
196+
initialContent: PartialBlock<
197+
typeof schema.blockSchema,
198+
typeof schema.inlineContentSchema
199+
>[] = [
200+
{
201+
type: 'paragraph',
202+
content: 'Welcome to this demo!',
203+
},
204+
{
205+
type: 'paragraph',
206+
content: [
207+
{
208+
type: 'mention',
209+
props: {
210+
user: 'Steve',
211+
},
212+
},
213+
{
214+
type: 'text',
215+
text: ' <- This is an example mention',
216+
styles: {},
217+
},
218+
],
219+
},
220+
{
221+
type: 'paragraph',
222+
content: "Press the '@' key to open the mentions menu and add another",
223+
},
224+
{
225+
type: 'paragraph',
226+
},
227+
];
228+
options: BlockNoteEditorOptionsType = { schema };
229+
230+
onEditorReady($event: BlockNoteEditor<any, any, any>) {
231+
this.items = getMentionMenuItems($event);
232+
}
233+
}`;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { CommonModule } from '@angular/common';
2+
import { Component } from '@angular/core';
3+
import {
4+
BnaEditorComponent,
5+
HlmButtonDirective,
6+
hlmP,
7+
HlmTabsComponent,
8+
} from '@dytab/block-note-angular';
9+
import { CodeComponent } from '../../../../shared/code/code.component';
10+
import { DemoBoxComponent } from '../../../../shared/layout/demo-box.component';
11+
import { TabsComponent } from '../../../../shared/layout/example-tabs.component';
12+
import { SectionIntroComponent } from '../../../../shared/layout/section-intro.component';
13+
import {
14+
MentionsMenuExample,
15+
mentionsMenuExampleCode,
16+
} from './mentions-menu.example';
17+
18+
@Component({
19+
standalone: true,
20+
imports: [
21+
CommonModule,
22+
BnaEditorComponent,
23+
HlmButtonDirective,
24+
SectionIntroComponent,
25+
CodeComponent,
26+
DemoBoxComponent,
27+
HlmTabsComponent,
28+
TabsComponent,
29+
MentionsMenuExample,
30+
],
31+
template: `<bna-section-intro name="Mentions Menu">
32+
<p class="${hlmP} mb-8">
33+
In this example, we create a custom Mention inline content type which is
34+
used to tag people. In addition, we create a new Suggestion Menu for
35+
mentions which opens with the "&#64;" character.
36+
</p>
37+
<p>
38+
<strong>Try it out</strong>: Press the "&#64;" key to open the mentions
39+
menu and insert a mention!
40+
</p>
41+
</bna-section-intro>
42+
<hlm-tabs tab="preview">
43+
<bna-example-tabs firstTab="Preview" secondTab="Code">
44+
<bna-demo-box firstTab>
45+
<bna-mentions-menu-example />
46+
</bna-demo-box>
47+
<bna-code [code]="exampleCode" secondTab />
48+
</bna-example-tabs>
49+
</hlm-tabs>`,
50+
})
51+
export class MentionsMenuPage {
52+
exampleCode = mentionsMenuExampleCode;
53+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { createInlineContentSpec } from '@blocknote/core';
2+
import { InlineContentFromConfig } from '@blocknote/core/types/src/schema/inlineContent/types';
3+
4+
export const mentionConfig = {
5+
type: 'mention',
6+
propSchema: {
7+
user: {
8+
default: 'Unknown',
9+
},
10+
},
11+
content: 'none',
12+
} as const;
13+
14+
export type MentionConfigType = typeof mentionConfig;
15+
16+
const render = (
17+
inlineContent: InlineContentFromConfig<MentionConfigType, any>
18+
) => {
19+
const div = document.createElement('span');
20+
div.style.backgroundColor = '#9d9';
21+
div.style.width = '100%';
22+
div.style.padding = '4px 8px';
23+
div.style.borderRadius = '4px';
24+
div.innerHTML = `${inlineContent.props.user}`;
25+
console.log(inlineContent);
26+
return {
27+
dom: div,
28+
};
29+
};
30+
31+
export const Mention = createInlineContentSpec(mentionConfig, {
32+
render: render,
33+
});

docs/src/pages/examples/examples.page.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ import { HlmButtonDirective } from '@dytab/block-note-angular';
104104
routerLink="custom/api-content-block"
105105
>Api Content Block</a
106106
>
107+
<a
108+
hlmBtn
109+
variant="ghost"
110+
class="justify-start"
111+
routerLinkActive="active-link"
112+
routerLink="custom/mentions-menu"
113+
>Mentions Menu</a
114+
>
107115
Interoperability
108116
<a
109117
hlmBtn

0 commit comments

Comments
 (0)