Show scripture text with drawable overlay in draw mode
DrawCanvas now accepts a headerContent prop — when provided, a transparent canvas extends over the scripture text so you can draw directly on the verses, with ruled notebook space below for additional notes. Study page draw mode shows the full chunk passage this way instead of a compact unwritable strip. Reader page draw mode replaces the verse list with the same combined layout (all chapter verses + notebook canvas), hiding the verse list while active. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+27
-12
@@ -13,7 +13,9 @@ const INK_SIZES = [
|
|||||||
// strokes: array of saved stroke objects
|
// strokes: array of saved stroke objects
|
||||||
// onStrokesChange: (newStrokes) => void
|
// onStrokesChange: (newStrokes) => void
|
||||||
// onDone: optional () => void — shows "Done" button when provided
|
// onDone: optional () => void — shows "Done" button when provided
|
||||||
export default function DrawCanvas({ strokes, onStrokesChange, onDone }) {
|
// headerContent: optional JSX rendered above the notebook area.
|
||||||
|
// The canvas extends over it so you can draw directly on the content.
|
||||||
|
export default function DrawCanvas({ strokes, onStrokesChange, onDone, headerContent }) {
|
||||||
const { drawTool, setDrawTool, drawColor, setDrawColor, drawSize, setDrawSize } = useApp();
|
const { drawTool, setDrawTool, drawColor, setDrawColor, drawSize, setDrawSize } = useApp();
|
||||||
|
|
||||||
const canvasRef = useRef(null);
|
const canvasRef = useRef(null);
|
||||||
@@ -200,17 +202,30 @@ export default function DrawCanvas({ strokes, onStrokesChange, onDone }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Notebook canvas */}
|
{/* Draw surface: optional scripture header + ruled notebook, one canvas over both */}
|
||||||
<div
|
<div className="relative">
|
||||||
className="relative"
|
{/* Scripture content — canvas sits on top so you can draw directly on the text */}
|
||||||
style={{
|
{headerContent && (
|
||||||
minHeight: 640,
|
<div
|
||||||
background: 'white',
|
className="border-b border-slate-200 bg-slate-50 p-4 font-serif text-sm leading-relaxed text-slate-800"
|
||||||
backgroundImage: 'repeating-linear-gradient(transparent 0px, transparent 31px, #dde3ec 31px, #dde3ec 32px)',
|
style={{ pointerEvents: 'none', userSelect: 'none' }}
|
||||||
}}
|
>
|
||||||
>
|
{headerContent}
|
||||||
{/* Red margin line */}
|
</div>
|
||||||
<div className="absolute bottom-0 left-10 top-0 w-px bg-rose-200" style={{ zIndex: 1 }} />
|
)}
|
||||||
|
{/* Ruled notebook area */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
minHeight: 640,
|
||||||
|
background: 'white',
|
||||||
|
backgroundImage: 'repeating-linear-gradient(transparent 0px, transparent 31px, #dde3ec 31px, #dde3ec 32px)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* Red margin line — only in pure-notebook mode */}
|
||||||
|
{!headerContent && (
|
||||||
|
<div className="absolute bottom-0 left-10 top-0 w-px bg-rose-200" style={{ zIndex: 1 }} />
|
||||||
|
)}
|
||||||
|
{/* Single canvas spanning the entire area (scripture + notebook) */}
|
||||||
<canvas
|
<canvas
|
||||||
ref={canvasRef}
|
ref={canvasRef}
|
||||||
className="absolute inset-0 h-full w-full"
|
className="absolute inset-0 h-full w-full"
|
||||||
|
|||||||
@@ -300,8 +300,8 @@ export default function ReaderPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Verses */}
|
{/* Verses — hidden when draw mode is active */}
|
||||||
<div className="rounded-3xl border border-slate-200 bg-white p-6 shadow-panel">
|
<div className={`rounded-3xl border border-slate-200 bg-white p-6 shadow-panel${readerDrawMode ? ' hidden' : ''}`}>
|
||||||
<h2 className="mb-1 text-xl font-semibold text-slate-900">
|
<h2 className="mb-1 text-xl font-semibold text-slate-900">
|
||||||
{readerBook?.name} {readerChapter} <span className="text-sm font-normal text-slate-500">(BSB)</span>
|
{readerBook?.name} {readerChapter} <span className="text-sm font-normal text-slate-500">(BSB)</span>
|
||||||
</h2>
|
</h2>
|
||||||
@@ -433,13 +433,27 @@ export default function ReaderPage() {
|
|||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Ink notebook — shown when Draw mode is active */}
|
{/* Draw mode — scripture text visible with canvas overlay + ruled notebook below */}
|
||||||
{readerDrawMode && (
|
{readerDrawMode && (
|
||||||
<div className="mt-4">
|
<div>
|
||||||
<DrawCanvas
|
<DrawCanvas
|
||||||
strokes={readerPageInkStrokes}
|
strokes={readerPageInkStrokes}
|
||||||
onStrokesChange={(s) => updateReaderPageInk(readerBookAbbrev, readerChapter, s)}
|
onStrokesChange={(s) => updateReaderPageInk(readerBookAbbrev, readerChapter, s)}
|
||||||
onDone={() => setReaderDrawMode(false)}
|
onDone={() => setReaderDrawMode(false)}
|
||||||
|
headerContent={
|
||||||
|
<>
|
||||||
|
<div className="mb-2 flex items-center gap-2">
|
||||||
|
<span className="font-semibold text-slate-700">{readerBook?.name} {readerChapter}</span>
|
||||||
|
<span className="text-xs text-slate-400">BSB · draw on me</span>
|
||||||
|
</div>
|
||||||
|
{!readerLoading && readerVerses.map((v) => (
|
||||||
|
<p key={v.number} className="mb-1">
|
||||||
|
<span className="font-semibold text-slate-900">{v.number}.</span>{' '}
|
||||||
|
{v.text}
|
||||||
|
</p>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+19
-23
@@ -244,31 +244,27 @@ export default function StudyPage() {
|
|||||||
{selectedChunk ? (
|
{selectedChunk ? (
|
||||||
<div className="mt-6 space-y-6">
|
<div className="mt-6 space-y-6">
|
||||||
{studyLayout === 'annotate' ? (
|
{studyLayout === 'annotate' ? (
|
||||||
<div className="space-y-4">
|
<DrawCanvas
|
||||||
{/* Compact scripture strip */}
|
strokes={selectedChunk.inkStrokes ?? []}
|
||||||
<div className="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3">
|
onStrokesChange={(s) => updateChunk(selectedChunk.id, { inkStrokes: s })}
|
||||||
<div className="mb-1.5 flex items-center justify-between gap-2">
|
onDone={() => setStudyLayout('stacked')}
|
||||||
<span className="text-xs font-semibold uppercase tracking-[0.18em] text-slate-400">Scripture · read-only</span>
|
headerContent={
|
||||||
<span className="rounded-full bg-slate-200 px-2.5 py-0.5 text-xs font-semibold text-slate-600">
|
<>
|
||||||
{formatChunkReference(project, selectedChunkChapterIndex, selectedChunk, '–')}
|
<div className="mb-2 flex items-center justify-between gap-2">
|
||||||
</span>
|
<span className="text-xs font-semibold uppercase tracking-[0.18em] text-slate-400">Scripture · draw on me</span>
|
||||||
</div>
|
<span className="rounded-full bg-slate-200 px-2.5 py-0.5 text-xs font-semibold text-slate-600">
|
||||||
<p className="font-serif text-sm leading-relaxed text-slate-700">
|
{formatChunkReference(project, selectedChunkChapterIndex, selectedChunk, '–')}
|
||||||
{selectedChunkVerses.map((verse) => (
|
|
||||||
<span key={`${verse.chapter}-${verse.number}`}>
|
|
||||||
<span className="font-semibold text-slate-900">{verse.chapter}:{verse.number} </span>
|
|
||||||
{verse.text}{' '}
|
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
{selectedChunkVerses.map((verse) => (
|
||||||
|
<p key={`${verse.chapter}-${verse.number}`} className="mb-1">
|
||||||
|
<span className="font-semibold text-slate-900">{verse.chapter}:{verse.number}.</span>{' '}
|
||||||
|
{verse.text}
|
||||||
|
</p>
|
||||||
))}
|
))}
|
||||||
</p>
|
</>
|
||||||
</div>
|
}
|
||||||
{/* Notebook canvas */}
|
/>
|
||||||
<DrawCanvas
|
|
||||||
strokes={selectedChunk.inkStrokes ?? []}
|
|
||||||
onStrokesChange={(s) => updateChunk(selectedChunk.id, { inkStrokes: s })}
|
|
||||||
onDone={() => setStudyLayout('stacked')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<div className={`space-y-6 ${studyLayout === 'split' ? 'lg:flex lg:items-start lg:gap-6 lg:space-y-0' : ''}`}>
|
<div className={`space-y-6 ${studyLayout === 'split' ? 'lg:flex lg:items-start lg:gap-6 lg:space-y-0' : ''}`}>
|
||||||
{/* Scripture */}
|
{/* Scripture */}
|
||||||
|
|||||||
Reference in New Issue
Block a user