From 2a946db38f07b2c8206c337c06656836a08fe2f0 Mon Sep 17 00:00:00 2001 From: Nick the Sick Date: Tue, 9 Dec 2025 17:03:57 +0100 Subject: [PATCH] feat: allow customizing the rendering of video and audio elements #2203 --- packages/core/src/blocks/Audio/block.ts | 28 +++++++++++++++++++- packages/core/src/blocks/Video/block.ts | 34 +++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/packages/core/src/blocks/Audio/block.ts b/packages/core/src/blocks/Audio/block.ts index f271fcb16a..4d771ca837 100644 --- a/packages/core/src/blocks/Audio/block.ts +++ b/packages/core/src/blocks/Audio/block.ts @@ -15,7 +15,27 @@ export const FILE_AUDIO_ICON_SVG = ''; export interface AudioOptions { + /** + * The icon to use for the audio block. As an HTML string. + */ icon?: string; + /** + * Allows overriding the default audio element rendering. + */ + render?: (ctx: { + /** + * The default audio element which you can modify. + */ + element: HTMLAudioElement; + /** + * The block being rendered. + */ + block: BlockFromConfig; + /** + * The editor instance. + */ + editor: BlockNoteEditor<{ audio: AudioBlockConfig }, any, any>; + }) => HTMLAudioElement; } export type AudioBlockConfig = ReturnType; @@ -110,10 +130,16 @@ export const audioRender = audio.contentEditable = "false"; audio.draggable = false; + const audioElement = config.render?.({ + element: audio, + block, + editor, + }); + return createFileBlockWrapper( block, editor, - { dom: audio }, + { dom: audioElement ?? audio }, icon.firstElementChild as HTMLElement, ); }; diff --git a/packages/core/src/blocks/Video/block.ts b/packages/core/src/blocks/Video/block.ts index 026b333ba5..87e300e388 100644 --- a/packages/core/src/blocks/Video/block.ts +++ b/packages/core/src/blocks/Video/block.ts @@ -1,4 +1,9 @@ -import { createBlockConfig, createBlockSpec } from "../../schema/index.js"; +import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js"; +import { + BlockFromConfig, + createBlockConfig, + createBlockSpec, +} from "../../schema/index.js"; import { defaultProps, parseDefaultProps } from "../defaultProps.js"; import { parseFigureElement } from "../File/helpers/parse/parseFigureElement.js"; import { createResizableFileBlockWrapper } from "../File/helpers/render/createResizableFileBlockWrapper.js"; @@ -10,7 +15,27 @@ export const FILE_VIDEO_ICON_SVG = ''; export interface VideoOptions { + /** + * The icon to use for the video block. As an HTML string. + */ icon?: string; + /** + * Allows overriding the default video element rendering. + */ + render?: (ctx: { + /** + * The default video element which you can modify. + */ + element: HTMLVideoElement; + /** + * The block being rendered. + */ + block: BlockFromConfig; + /** + * The editor instance. + */ + editor: BlockNoteEditor<{ video: VideoBlockConfig }, any, any>; + }) => HTMLVideoElement; } export type VideoBlockConfig = ReturnType; @@ -93,7 +118,12 @@ export const createVideoBlockSpec = createBlockSpec( video.contentEditable = "false"; video.draggable = false; video.width = block.props.previewWidth; - videoWrapper.appendChild(video); + const videoElement = config.render?.({ + element: video, + block, + editor, + }); + videoWrapper.appendChild(videoElement ?? video); return createResizableFileBlockWrapper( block,