mirror of https://github.com/buster-so/buster.git
view port update
This commit is contained in:
parent
4ac600e4bb
commit
bb0adc8cb8
|
@ -1,5 +1,12 @@
|
|||
import type { SuggestionProps } from '@tiptap/suggestion';
|
||||
import React, { useEffect, useImperativeHandle, useState } from 'react';
|
||||
import React, {
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type {
|
||||
MentionInputTriggerItem,
|
||||
|
@ -26,6 +33,7 @@ function MentionListInner<T = string>(
|
|||
{ trigger, emptyState, items, command, className }: MentionListProps<T>,
|
||||
ref: React.ForwardedRef<MentionListImperativeHandle>
|
||||
) {
|
||||
const listRef = useRef<HTMLDivElement>(null);
|
||||
const [selectedItem, setSelectedItem] = useState<T | undefined>(undefined);
|
||||
|
||||
const selectItem = (value: T) => {
|
||||
|
@ -98,30 +106,55 @@ function MentionListInner<T = string>(
|
|||
}));
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col p-1 bg-background rounded border w-full min-w-[200px] max-w-[280px] overflow-x-auto',
|
||||
'max-h-[300px] overflow-y-auto',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{items.length ? (
|
||||
items.map((item, index: number) => (
|
||||
<MentionListSelector<T>
|
||||
key={index}
|
||||
{...item}
|
||||
selectedItem={selectedItem}
|
||||
setSelectedItem={setSelectedItem}
|
||||
onSelectItem={selectItem}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<div className="text-gray-light">{emptyState || 'No results'}</div>
|
||||
)}
|
||||
</div>
|
||||
<MentionListProvider listRef={listRef}>
|
||||
<div
|
||||
ref={listRef}
|
||||
data-testid="mention-list"
|
||||
className={cn(
|
||||
'flex flex-col p-1 bg-background rounded border w-full min-w-[200px] max-w-[280px] overflow-x-auto',
|
||||
'max-h-[300px] overflow-y-auto',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{items.length ? (
|
||||
items.map((item, index: number) => (
|
||||
<MentionListSelector<T>
|
||||
key={index}
|
||||
{...item}
|
||||
selectedItem={selectedItem}
|
||||
setSelectedItem={setSelectedItem}
|
||||
onSelectItem={selectItem}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<div className="text-gray-light">{emptyState || 'No results'}</div>
|
||||
)}
|
||||
</div>
|
||||
</MentionListProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export const MentionList = React.forwardRef(MentionListInner) as <T = string>(
|
||||
props: MentionListProps<T> & { ref?: React.ForwardedRef<MentionListImperativeHandle> }
|
||||
) => ReturnType<typeof MentionListInner> & { displayName?: string };
|
||||
|
||||
const MentionListContext = createContext<{
|
||||
listRef: React.RefObject<HTMLDivElement | null> | null;
|
||||
}>({
|
||||
listRef: null,
|
||||
});
|
||||
|
||||
const MentionListProvider = ({
|
||||
children,
|
||||
listRef,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
listRef: React.RefObject<HTMLDivElement | null>;
|
||||
}) => {
|
||||
return <MentionListContext.Provider value={{ listRef }}>{children}</MentionListContext.Provider>;
|
||||
};
|
||||
|
||||
export const useMentionListRef = () => {
|
||||
const { listRef } = useContext(MentionListContext);
|
||||
return listRef;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { useEffect, useRef } from 'react';
|
||||
import { Text } from '@/components/ui/typography/Text';
|
||||
import { useInViewport } from '@/hooks/useInViewport';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useMentionListRef } from './MentionList';
|
||||
import type { MentionTriggerItemExtended } from './MentionListSelector';
|
||||
|
||||
export function MentionListItem<T = string>({
|
||||
|
@ -13,10 +16,14 @@ export function MentionListItem<T = string>({
|
|||
onSelectItem,
|
||||
secondaryContent,
|
||||
}: MentionTriggerItemExtended<T>) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
onClick={() => onSelectItem(value)}
|
||||
onMouseEnter={() => setSelectedItem(value)}
|
||||
data-testid={`mention-list-item-${value}`}
|
||||
data-disabled={disabled}
|
||||
data-loading={loading}
|
||||
data-selected={isSelected}
|
||||
|
|
|
@ -13,7 +13,6 @@ export const MentionPill = <T extends string>({
|
|||
editor,
|
||||
}: ReactNodeViewProps<MentionTriggerItem<T>>) => {
|
||||
const { trigger, label, value, pillLabel } = node.attrs as MentionPillAttributes;
|
||||
console.log('node', node);
|
||||
const pillStyling = editor.storage.mention.pillStylingByTrigger.get(trigger);
|
||||
const pillClassName =
|
||||
typeof pillStyling?.className === 'function'
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import type React from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { type RefObject, useEffect, useRef, useState } from 'react';
|
||||
|
||||
interface UseInViewportOptions {
|
||||
/** The percentage of the element that needs to be visible (0 to 1) */
|
||||
threshold?: number;
|
||||
/** Margin around the root element (viewport) */
|
||||
rootMargin?: string;
|
||||
root?: Element;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,6 +37,7 @@ export const useInViewport = (
|
|||
{
|
||||
threshold: options.threshold ?? 0,
|
||||
rootMargin: options.rootMargin ?? '0px',
|
||||
root: options.root,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -49,7 +51,7 @@ export const useInViewport = (
|
|||
observer.unobserve(currentRef);
|
||||
}
|
||||
};
|
||||
}, [ref, options.threshold, options.rootMargin]);
|
||||
}, [ref, options.threshold, options.rootMargin, options.root]);
|
||||
|
||||
return [inViewport] as const;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue