Merge branch 'main' into pr-736

This commit is contained in:
github-actions[bot]
2026-05-24 09:01:10 +00:00
committed by GitHub
2 changed files with 63 additions and 1 deletions

View File

@@ -287,6 +287,29 @@ describe('tolariaEditorFormatting behavior', () => {
}))
})
it('adds viewport-clamping middleware and preserves caller middleware', () => {
const editor = createMockEditor('paragraph')
useBlockNoteEditorMock.mockReturnValue(editor)
render(
<TolariaFormattingToolbarController
floatingUIOptions={{
useFloatingOptions: {
middleware: [{ name: 'custom-middleware' } as never],
},
}}
/>,
)
const floatingOptions = positionPopoverState.lastProps?.useFloatingOptions as {
middleware: Array<{ name: string }>
}
expect(floatingOptions.middleware.map((middleware) => middleware.name)).toEqual(
expect.arrayContaining(['custom-middleware', 'tolariaViewportClamp']),
)
})
it('falls back to top-start and focuses the block type trigger on mouse down', () => {
const editor = createMockEditor('paragraph')
const focusSpy = vi.spyOn(HTMLButtonElement.prototype, 'focus').mockImplementation(() => {})

View File

@@ -67,6 +67,9 @@ import {
type TolariaBasicTextStyle = 'bold' | 'italic' | 'strike' | 'code'
const FORMATTER_CLOSE_GRACE_MS = 160
const FORMATTER_VIEWPORT_PADDING_PX = 8
type TolariaFloatingOptions = NonNullable<FloatingUIOptions['useFloatingOptions']>
type TolariaFloatingMiddleware = NonNullable<TolariaFloatingOptions['middleware']>[number]
function isFocusStillWithinToolbar(
currentTarget: EventTarget & Element,
@@ -230,6 +233,42 @@ function textAlignmentToPlacement(
}
}
function viewportClampMiddleware(): TolariaFloatingMiddleware {
return {
name: 'tolariaViewportClamp',
fn({ x, rects }: { rects: { floating: { width: number } }; x: number }) {
const viewportWidth = window.visualViewport?.width ?? window.innerWidth
const minX = FORMATTER_VIEWPORT_PADDING_PX
const maxX = Math.max(
minX,
viewportWidth - rects.floating.width - FORMATTER_VIEWPORT_PADDING_PX,
)
return {
x: Math.min(Math.max(x, minX), maxX),
}
},
}
}
function withViewportSafeMiddleware(
options?: TolariaFloatingOptions,
): TolariaFloatingOptions {
if (!options) {
return {
middleware: [viewportClampMiddleware()],
}
}
return {
...options,
middleware: [
...(options.middleware ?? []),
viewportClampMiddleware(),
],
}
}
function editorSupportsTextStyle(
style: TolariaBasicTextStyle,
editor: BlockNoteEditor<BlockSchema, InlineContentSchema, StyleSchema>,
@@ -730,7 +769,7 @@ export function TolariaFormattingToolbarController(props: {
}
},
placement,
...props.floatingUIOptions?.useFloatingOptions,
...withViewportSafeMiddleware(props.floatingUIOptions?.useFloatingOptions),
},
elementProps: {
style: {