From ce7014d6f74d929488cb0c277f7015a5abc90b0e Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 8 Nov 2024 08:03:28 +0100 Subject: [PATCH] Added optional FloatingArrow to TextAnnotatorPopup --- .../TextAnnotatorPopup/TextAnnotatorPopup.tsx | 39 +++++++++++++++---- packages/text-annotator-react/test/App.tsx | 4 ++ packages/text-annotator-react/test/index.html | 1 + 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index 26c05271..12d4adc4 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -1,10 +1,13 @@ -import { ReactNode, useEffect, useMemo, useState } from 'react'; +import { ReactNode, useEffect, useMemo, useRef, useState } from 'react'; import { useAnnotator, useSelection } from '@annotorious/react'; import { isRevived, NOT_ANNOTATABLE_CLASS, TextAnnotation, TextAnnotator } from '@recogito/text-annotator'; import { isMobile } from './isMobile'; import { + arrow, autoUpdate, flip, + FloatingArrow, + FloatingArrowProps, FloatingFocusManager, FloatingPortal, inline, @@ -22,6 +25,10 @@ interface TextAnnotationPopupProps { ariaCloseWarning?: string; + arrow?: boolean; + + arrowProps?: Omit; + popup(props: TextAnnotationPopupContentProps): ReactNode; } @@ -46,6 +53,22 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { const [isOpen, setOpen] = useState(selected?.length > 0); + const arrowRef = useRef(null); + + // Conditional floating-ui middleware + const middleware = useMemo(() => { + const m = [ + inline(), + offset(10), + flip({ crossAxis: true }), + shift({ crossAxis: true, padding: 10 }) + ]; + + return props.arrow + ? [...m, arrow({ element: arrowRef }) ] + : m; + }, [props.arrow]); + const { refs, floatingStyles, update, context } = useFloating({ placement: isMobile() ? 'bottom' : 'top', open: isOpen, @@ -55,12 +78,7 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { r?.cancelSelected(); } }, - middleware: [ - offset(10), - inline(), - flip(), - shift({ mainAxis: false, crossAxis: true, padding: 10 }) - ], + middleware, whileElementsMounted: autoUpdate }); @@ -132,6 +150,13 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { event })} + {props.arrow && ( + + )} + diff --git a/packages/text-annotator-react/test/App.tsx b/packages/text-annotator-react/test/App.tsx index 74849e2c..25b543e9 100644 --- a/packages/text-annotator-react/test/App.tsx +++ b/packages/text-annotator-react/test/App.tsx @@ -190,6 +190,10 @@ export const App: FC = () => { () } diff --git a/packages/text-annotator-react/test/index.html b/packages/text-annotator-react/test/index.html index 3f33c769..ba514892 100644 --- a/packages/text-annotator-react/test/index.html +++ b/packages/text-annotator-react/test/index.html @@ -26,6 +26,7 @@ p { font-size: 17px; line-height: 160%; + min-width: 600px; } .r6o-popup {