Skip to content
File

Blob: src/shared/editor/presentation/page-mention.tsx

typescript85 lines
1import { FileText, Lock } from "lucide-react";
2import type { KeyboardEventHandler, MouseEventHandler, ReactNode } from "react";
3 
4export type PageMentionPresentationKind = "accessible" | "pending" | "restricted";
5 
6export interface PageMentionPresentationProps {
7 pageId?: string | null;
8 label?: string | null;
9 icon?: ReactNode;
10 href?: string | null;
11 kind?: PageMentionPresentationKind;
12 ariaLabel?: string;
13 onClick?: MouseEventHandler;
14 onKeyDown?: KeyboardEventHandler;
15 tabIndex?: number;
16}
17 
18export function PageMentionContent({
19 icon,
20 label,
21 restricted,
22}: {
23 icon?: ReactNode;
24 label: string;
25 restricted?: boolean;
26}) {
27 return (
28 <>
29 <span className="tiptap-page-mention-icon" aria-hidden="true">
30 {icon ?? (restricted ? <Lock size={12} className="shrink-0" /> : <FileText size={12} />)}
31 </span>
32 <span className="tiptap-page-mention-label">{label}</span>
33 </>
34 );
35}
36 
37export function PageMentionPresentation({
38 pageId,
39 label,
40 icon,
41 href,
42 kind = "accessible",
43 ariaLabel,
44 onClick,
45 onKeyDown,
46 tabIndex,
47}: PageMentionPresentationProps) {
48 const resolvedKind = pageId ? kind : "restricted";
49 const resolvedLabel = label?.trim() || (resolvedKind === "restricted" ? "Restricted" : "Untitled");
50 const className = [
51 "tiptap-page-mention",
52 resolvedKind === "pending" ? "tiptap-page-mention--pending" : "",
53 resolvedKind === "restricted" ? "tiptap-page-mention--restricted" : "",
54 ]
55 .filter(Boolean)
56 .join(" ");
57 
58 const commonProps = {
59 className,
60 "data-page-id": pageId || undefined,
61 "data-page-mention": "",
62 "aria-label": ariaLabel,
63 "aria-disabled": resolvedKind === "accessible" ? undefined : true,
64 onClick,
65 onKeyDown,
66 tabIndex,
67 };
68 
69 const content = <PageMentionContent icon={icon} label={resolvedLabel} restricted={resolvedKind === "restricted"} />;
70 
71 if (href && resolvedKind === "accessible") {
72 return (
73 <a {...commonProps} href={href}>
74 {content}
75 </a>
76 );
77 }
78 
79 return (
80 <span {...commonProps} role={resolvedKind === "accessible" ? "link" : undefined}>
81 {content}
82 </span>
83 );
84}