e.stopPropagation()}>
{(() => {
const sp = gallery.subpages[expandedSubpage];
const spIndex = expandedSubpage;
return (
<>
{drawerMode === 'preview' ? (
{sp.title || sp.name || 'Untitled Page'}
{sp.subtitle &&
{sp.subtitle}
}
{sp.sections && sp.sections.length > 0 ? (
sp.sections.map((sec, sIdx) => (
{sec.title || 'Untitled Section'}
{sec.description &&
{sec.description}
}
{sec.albums.map((alb, aIdx) => {
const immichAlb = immichAlbums.find((a) => a.id === alb.id);
const thumb = alb.heroImage || immichAlb?.thumbnailAssetId;
return (
{thumb ? (

) : (
)}
{alb.title || immichAlb?.albumName || alb.id}
);
})}
))
) : (
{sp.albums.map((alb, aIdx) => {
const immichAlb = immichAlbums.find((a) => a.id === alb.id);
const thumb = alb.heroImage || immichAlb?.thumbnailAssetId;
return (
{thumb ? (

) : (
)}
{alb.title || immichAlb?.albumName || alb.id}
);
})}
)}
) : (
<>
{/* Subpage metadata */}
{/* Visual Photo Essay Builder (if layout === 'essay') */}
{(sp.grid?.layout === 'essay' || sp.essayText != null) && (
📖 Storytelling & Photo Essay Builder
Compose text, quotes, and fullbleed/wide photos visually.
updateSubpage(spIndex, { essayText: newMarkdown })}
onSelectPhoto={(callback) => {
setPickerTarget({ type: 'subpage', subpageIndex: spIndex });
// We can pass a photo picker handler if needed
}}
/>
)}
{/* Albums (if no sections) with DnD */}
{(!sp.sections || sp.sections.length === 0) && (
Albums in this Page
`album-${a.id}-${i}`)}
strategy={verticalListSortingStrategy}
>
{sp.albums.length === 0 && (
No albums added yet. Click + Add Album to pick from Immich.
)}
{sp.albums.map((album, aIndex) => (
removeSubpageAlbum(spIndex, aIndex)}
onEdit={() => setEditingAlbumAddress({ type: 'subpage', subpageIndex: spIndex, albumIndex: aIndex })}
/>
))}
)}
{/* Sections */}
{sp.sections && sp.sections.length > 0 && (
{sp.sections.map((sec, secIndex) => (
updateSection(spIndex, secIndex, { title: e.target.value })
}
placeholder="Section title"
/>
updateSection(spIndex, secIndex, {
description: e.target.value || undefined,
})
}
placeholder="Section description (optional)"
className="section-desc-input"
/>
{sec.albums.map((album, aIndex) => (
removeSectionAlbum(spIndex, secIndex, aIndex)}
onEdit={() => setEditingAlbumAddress({ type: 'section', subpageIndex: spIndex, sectionIndex: secIndex, albumIndex: aIndex })}
/>
))}
))}
)}
{sp.sections && sp.sections.length > 0 && (
)}
>
)}