Skip to content

Commit 8493a69

Browse files
committed
feat: add alert block custom inline reuse block-note vanillajs example
1 parent 8439a7f commit 8493a69

File tree

2 files changed

+91
-136
lines changed

2 files changed

+91
-136
lines changed

docs/src/pages/examples/custom/alert-block/alert-block.example.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export class AlertBlockExample {
4040
props: {
4141
type: 'warning',
4242
},
43+
content: 'Hallo Welt.',
4344
},
4445
];
4546
options: BlockNoteEditorOptionsType<
Lines changed: 90 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,102 @@
1-
import {
2-
BlockFromConfig,
3-
BlockNoteEditor,
4-
createBlockSpec,
5-
Props,
6-
PropSchema,
7-
} from '@blocknote/core';
8-
import {
9-
lucideAlertTriangle,
10-
lucideCheckCircle,
11-
lucideCircleOff,
12-
lucideInfo,
13-
} from '@ng-icons/lucide';
1+
import { createBlockSpec, defaultProps } from '@blocknote/core';
142

15-
// The types of alerts that users can choose from.
16-
export const alertTypes = [
17-
{
18-
title: 'Warning',
19-
value: 'warning',
20-
icon: lucideAlertTriangle,
3+
// The types of alerts that users can choose from
4+
const alertTypes = {
5+
warning: {
6+
icon: '⚠️',
217
color: '#e69819',
22-
backgroundColor: {
23-
light: '#fff6e6',
24-
dark: '#805d20',
25-
},
8+
backgroundColor: '#fff6e6',
269
},
27-
{
28-
title: 'Error',
29-
value: 'error',
30-
icon: lucideCircleOff,
10+
error: {
11+
icon: '⛔',
3112
color: '#d80d0d',
32-
backgroundColor: {
33-
light: '#ffe6e6',
34-
dark: '#802020',
35-
},
13+
backgroundColor: '#ffe6e6',
3614
},
37-
{
38-
title: 'Info',
39-
value: 'info',
40-
icon: lucideInfo,
15+
info: {
16+
icon: 'ℹ️',
4117
color: '#507aff',
42-
backgroundColor: {
43-
light: '#e6ebff',
44-
dark: '#203380',
45-
},
18+
backgroundColor: '#e6ebff',
4619
},
47-
{
48-
title: 'Success',
49-
value: 'success',
50-
icon: lucideCheckCircle,
20+
success: {
21+
icon: '✅',
5122
color: '#0bc10b',
52-
backgroundColor: {
53-
light: '#e6ffe6',
54-
dark: '#208020',
55-
},
23+
backgroundColor: '#e6ffe6',
5624
},
57-
] as const;
25+
};
5826

59-
export const alertPropSchema = {
60-
type: {
61-
default: 'warning',
62-
values: alertTypes.map((type) => type.value),
27+
export const alertBlock = createBlockSpec(
28+
{
29+
type: 'alert',
30+
propSchema: {
31+
textAlignment: defaultProps.textAlignment,
32+
textColor: defaultProps.textColor,
33+
type: {
34+
default: 'warning',
35+
values: ['warning', 'error', 'info', 'success'] as const,
36+
},
37+
},
38+
content: 'inline',
6339
},
64-
} satisfies PropSchema;
65-
66-
export const alertBlockConfig = {
67-
type: 'alert' as const,
68-
propSchema: alertPropSchema,
69-
content: 'inline',
70-
} as const;
71-
72-
const alertRender = (
73-
block: BlockFromConfig<typeof alertBlockConfig, any, any>,
74-
editor: BlockNoteEditor<any, any, any>
75-
) => {
76-
const div = document.createElement('div');
77-
div.style.width = '100%';
78-
div.style.padding = '4px 8px';
79-
div.style.display = 'flex';
80-
div.style.alignItems = 'center';
81-
const alertType = alertTypes.find((type) => type.value === block.props.type);
82-
if (!alertType) {
83-
return {
84-
dom: div,
85-
};
40+
{
41+
render: (block, editor) => {
42+
const alert = document.createElement('div');
43+
alert.className = 'alert';
44+
alert.style.width = '100%';
45+
alert.style.display = 'flex';
46+
alert.style.backgroundColor =
47+
alertTypes[block.props.type].backgroundColor;
48+
49+
const dropdown = document.createElement('select');
50+
dropdown.contentEditable = 'false';
51+
dropdown.addEventListener('change', () => {
52+
editor.updateBlock(block, {
53+
type: 'alert',
54+
props: { type: dropdown.value as keyof typeof alertTypes },
55+
});
56+
});
57+
dropdown.options.add(
58+
new Option(
59+
alertTypes['warning'].icon,
60+
'warning',
61+
block.props.type === 'warning',
62+
block.props.type === 'warning'
63+
)
64+
);
65+
dropdown.options.add(
66+
new Option(
67+
alertTypes['error'].icon,
68+
'error',
69+
block.props.type === 'error',
70+
block.props.type === 'error'
71+
)
72+
);
73+
dropdown.options.add(
74+
new Option(
75+
alertTypes['info'].icon,
76+
'info',
77+
block.props.type === 'info',
78+
block.props.type === 'info'
79+
)
80+
);
81+
dropdown.options.add(
82+
new Option(
83+
alertTypes['success'].icon,
84+
'success',
85+
block.props.type === 'success',
86+
block.props.type === 'success'
87+
)
88+
);
89+
alert.appendChild(dropdown);
90+
91+
const inlineContent = document.createElement('div');
92+
inlineContent.style.flexGrow = '1';
93+
94+
alert.appendChild(inlineContent);
95+
96+
return {
97+
dom: alert,
98+
contentDOM: inlineContent,
99+
};
100+
},
86101
}
87-
div.style.color = alertType.color;
88-
div.style.backgroundColor = alertType.backgroundColor.light;
89-
90-
// Create a select element.
91-
const selectElement = document.createElement('select');
92-
93-
// Populate the select element with options.
94-
alertTypes.forEach((alertType) => {
95-
const option = document.createElement('option');
96-
97-
option.value = alertType.value;
98-
option.text = alertType.title;
99-
100-
// Mark the current alertType as selected in the dropdown.
101-
if (alertType.value === block.props.type) {
102-
option.selected = true;
103-
}
104-
105-
selectElement.appendChild(option);
106-
});
107-
108-
// Handle the change event.
109-
selectElement.addEventListener('change', (event: Event) => {
110-
const target = event.target as HTMLSelectElement;
111-
editor.updateBlock(block, {
112-
type: 'alert',
113-
props: { type: target.value },
114-
});
115-
});
116-
117-
// Style the dropdown
118-
selectElement.style.position = 'absolute';
119-
selectElement.style.right = '100px';
120-
121-
// Add the select element to the div.
122-
div.appendChild(selectElement);
123-
124-
const iconElement = document.createElement('span');
125-
iconElement.innerHTML = alertType.icon;
126-
iconElement.style.marginRight = '8px';
127-
div.appendChild(iconElement);
128-
129-
const textElement = document.createElement('span');
130-
textElement.classList.add('inline-content');
131-
textElement.textContent = 'Hello world';
132-
div.appendChild(textElement);
133-
134-
return {
135-
dom: div,
136-
};
137-
};
138-
139-
export const alertParse = (
140-
element: HTMLElement
141-
): Partial<Props<typeof alertBlockConfig.propSchema>> | undefined => {
142-
return undefined;
143-
};
144-
145-
export const alertBlock = createBlockSpec(alertBlockConfig, {
146-
render: alertRender,
147-
parse: alertParse,
148-
});
102+
);

0 commit comments

Comments
 (0)