Merge branch 'main' into pr-736
This commit is contained in:
@@ -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(() => {})
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user