Archived
76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
import { useState } from "react";
|
|
import { useTranslation } from "react-i18n-lite";
|
|
import type { BookmarkRailItem } from "@/utils/bookmarkRailLayout";
|
|
import { truncateRailPreview } from "@/utils/bookmarkRailLayout";
|
|
import { normalizeHighlightColor } from "@/constants/bookmarkHighlightColors";
|
|
import { BookmarkIcon } from "./BookmarkIcon";
|
|
|
|
interface BookmarkReaderRailProps {
|
|
items: BookmarkRailItem[];
|
|
onGoToBookmark: (epubCfi: string) => void;
|
|
}
|
|
|
|
function RailMarker({
|
|
item,
|
|
onGoToBookmark,
|
|
}: {
|
|
item: BookmarkRailItem;
|
|
onGoToBookmark: (epubCfi: string) => void;
|
|
}) {
|
|
const { t } = useTranslation();
|
|
const [hovered, setHovered] = useState(false);
|
|
const color = normalizeHighlightColor(item.marker.highlight_color);
|
|
const previewText = truncateRailPreview(
|
|
item.marker.location_text || item.marker.chapter_title || "",
|
|
);
|
|
const notePreview = item.marker.content
|
|
? truncateRailPreview(item.marker.content, 80)
|
|
: "";
|
|
|
|
const ariaLabel = previewText
|
|
? t("reader.bookmarkRailPreview", { text: previewText })
|
|
: t("reader.bookmarkRailGoTo");
|
|
|
|
return (
|
|
<li className="reader-bookmark-marker-wrap">
|
|
<button
|
|
type="button"
|
|
className="reader-bookmark-marker"
|
|
onClick={() => onGoToBookmark(item.marker.epub_cfi)}
|
|
onMouseEnter={() => setHovered(true)}
|
|
onMouseLeave={() => setHovered(false)}
|
|
onFocus={() => setHovered(true)}
|
|
onBlur={() => setHovered(false)}
|
|
aria-label={ariaLabel}
|
|
title={previewText || undefined}
|
|
>
|
|
<BookmarkIcon size={28} color={color} className="reader-bookmark-marker-icon" />
|
|
</button>
|
|
{hovered && previewText && (
|
|
<div
|
|
className="reader-bookmark-preview"
|
|
style={{ borderLeftColor: color }}
|
|
role="tooltip"
|
|
>
|
|
<p className="reader-bookmark-preview-passage">{previewText}</p>
|
|
{notePreview && (
|
|
<p className="reader-bookmark-preview-note">{notePreview}</p>
|
|
)}
|
|
</div>
|
|
)}
|
|
</li>
|
|
);
|
|
}
|
|
|
|
export function BookmarkReaderRail({ items, onGoToBookmark }: BookmarkReaderRailProps) {
|
|
if (items.length === 0) return null;
|
|
|
|
return (
|
|
<ul className="reader-bookmark-strip" aria-label="Bookmarks">
|
|
{items.map((item) => (
|
|
<RailMarker key={item.marker.id} item={item} onGoToBookmark={onGoToBookmark} />
|
|
))}
|
|
</ul>
|
|
);
|
|
}
|