Files
study-bible-project/src/components/ScriptureRefs.jsx
T

64 lines
3.4 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Under a note: each Scripture reference written in it (Rom 8:28, Psalm 23…) as a chip. Click one to read the verse
// (BSB) right there, or open it in the Bible reader. The text itself is never changed.
import { useEffect, useMemo, useState } from 'react';
import { useApp } from '../context/AppContext.js';
import { fetchChapter } from '../utils/bibleText.js';
import { labelFor, uniqueReferences } from '../utils/scriptureRefs.js';
const MAX_VERSES = 12;
const CHAPTER_PREVIEW = 6;
function Preview({ r }) {
const { jumpToReaderVerse, openBibleReader } = useApp();
const [state, setState] = useState({ loading: true });
useEffect(() => {
let live = true;
setState({ loading: true });
fetchChapter('BSB', r.book, r.chapter)
.then(({ verses }) => {
const from = r.verse ?? 1;
const to = r.verse ? (r.endVerse ?? r.verse) : from + CHAPTER_PREVIEW - 1;
const picked = verses.filter((v) => v.number >= from && v.number <= to).slice(0, MAX_VERSES);
if (live) setState({ verses: picked, more: !r.verse && verses.length > picked.length });
})
.catch((err) => { if (live) setState({ error: err.message || 'Could not load the verse.' }); });
return () => { live = false; };
}, [r.book, r.chapter, r.verse, r.endVerse]);
return (
<div role="region" aria-label={`${labelFor(r)} preview`} className="mt-1.5 rounded-xl border border-[var(--r-line)] bg-[var(--r-bg)] p-3 text-[13px]">
{state.loading && <p className="text-xs text-[var(--r-sub)]">Loading…</p>}
{state.error && <p className="text-xs text-[var(--r-sub)]">{state.error} You can still open it in the Bible.</p>}
{state.verses && (state.verses.length === 0
? <p className="text-xs text-[var(--r-sub)]">That verse isn’t in the BSB.</p>
: <div className="space-y-1 font-serif leading-relaxed">{state.verses.map((v) => <p key={v.number}><sup className="mr-1 font-sans text-[var(--r-accent)]">{v.number}</sup>{v.text}</p>)}{state.more && <p className="text-xs text-[var(--r-sub)]">…</p>}</div>)}
<div className="mt-2 flex items-center gap-3 font-sans text-xs">
<button type="button" onClick={() => { jumpToReaderVerse(r.book, r.chapter, r.verse ?? 1); openBibleReader(); }} className="text-[var(--r-accent)] hover:underline">Read in the Bible</button>
<span className="text-[var(--r-sub)]">Berean Standard Bible</span>
</div>
</div>
);
}
export default function ScriptureRefs({ text }) {
const refs = useMemo(() => uniqueReferences(text), [text]);
const [open, setOpen] = useState(null);
if (refs.length === 0) return null;
const openRef = refs.find((r) => labelFor(r) === open);
return (
<div className="mt-1.5" aria-label="References in this note">
<p className="flex flex-wrap items-center gap-1.5 text-xs">
<span className="text-[var(--r-sub)]">Verses mentioned:</span>
{refs.map((r) => {
const label = labelFor(r);
return (
<button key={label} type="button" aria-pressed={open === label} onClick={() => setOpen(open === label ? null : label)}
className={`rounded-full border px-2 py-0.5 ${open === label ? 'border-[var(--r-accent)] text-[var(--r-text)]' : 'border-[var(--r-line)] text-[var(--r-accent)] hover:bg-black/5'}`}>{label}</button>
);
})}
</p>
{openRef && <Preview r={openRef} />}
</div>
);
}