feat(next-search): Implements document preview functionality #3221 (#9465)

### What problem does this PR solve?

feat(next-search): Implements document preview functionality

- Adds a new document preview modal component
- Implements document preview page logic
- Adds document preview-related hooks
- Optimizes document preview rendering logic
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
chanx
2025-08-14 12:11:53 +08:00
committed by GitHub
parent b55c3d07dc
commit b1baa91ff0
29 changed files with 1336 additions and 122 deletions

View File

@ -152,7 +152,7 @@ const Modal: ModalType = ({
onClick={() => maskClosable && onOpenChange?.(false)}
>
<DialogPrimitive.Content
className={`relative w-[700px] ${full ? 'max-w-full' : sizeClasses[size]} ${className} bg-colors-background-neutral-standard rounded-lg shadow-lg transition-all focus-visible:!outline-none`}
className={`relative w-[700px] ${full ? 'max-w-full' : sizeClasses[size]} ${className} bg-colors-background-neutral-standard rounded-lg shadow-lg border transition-all focus-visible:!outline-none`}
onClick={(e) => e.stopPropagation()}
>
{/* title */}

View File

@ -42,3 +42,92 @@ export const FormTooltip = ({ tooltip }: { tooltip: React.ReactNode }) => {
</Tooltip>
);
};
export interface AntToolTipProps {
title: React.ReactNode;
children: React.ReactNode;
placement?: 'top' | 'bottom' | 'left' | 'right';
trigger?: 'hover' | 'click' | 'focus';
className?: string;
}
export const AntToolTip: React.FC<AntToolTipProps> = ({
title,
children,
placement = 'top',
trigger = 'hover',
className,
}) => {
const [visible, setVisible] = React.useState(false);
const showTooltip = () => {
if (trigger === 'hover' || trigger === 'focus') {
setVisible(true);
}
};
const hideTooltip = () => {
if (trigger === 'hover' || trigger === 'focus') {
setVisible(false);
}
};
const toggleTooltip = () => {
if (trigger === 'click') {
setVisible(!visible);
}
};
const getPlacementClasses = () => {
switch (placement) {
case 'top':
return 'bottom-full left-1/2 transform -translate-x-1/2 mb-2';
case 'bottom':
return 'top-full left-1/2 transform -translate-x-1/2 mt-2';
case 'left':
return 'right-full top-1/2 transform -translate-y-1/2 mr-2';
case 'right':
return 'left-full top-1/2 transform -translate-y-1/2 ml-2';
default:
return 'bottom-full left-1/2 transform -translate-x-1/2 mb-2';
}
};
return (
<div className="inline-block relative">
<div
onMouseEnter={showTooltip}
onMouseLeave={hideTooltip}
onClick={toggleTooltip}
onFocus={showTooltip}
onBlur={hideTooltip}
>
{children}
</div>
{visible && title && (
<div
className={cn(
'absolute z-50 px-2.5 py-1.5 text-xs text-white bg-gray-800 rounded-sm shadow-sm whitespace-nowrap',
getPlacementClasses(),
className,
)}
>
{title}
<div
className={cn(
'absolute w-2 h-2 bg-gray-800',
placement === 'top' &&
'bottom-[-4px] left-1/2 transform -translate-x-1/2 rotate-45',
placement === 'bottom' &&
'top-[-4px] left-1/2 transform -translate-x-1/2 rotate-45',
placement === 'left' &&
'right-[-4px] top-1/2 transform -translate-y-1/2 rotate-45',
placement === 'right' &&
'left-[-4px] top-1/2 transform -translate-y-1/2 rotate-45',
)}
/>
</div>
)}
</div>
);
};