release: v0.12.0 (#520)

Forty-one commits since v0.11.0. See CHANGELOG.md for the full list and the upgrade notes.
This commit is contained in:
Ralksta
2026-08-23 23:18:14 +02:00
committed by GitHub
parent 2f546f440d
commit 10ec68f493
119 changed files with 6888 additions and 758 deletions

View File

@@ -31,7 +31,12 @@ import {
isAlbumSortMode,
type AlbumSortMode,
} from '@/lib/albumSort';
import type { AlbumEntryObject } from '@/lib/config/schema';
import {
COVER_GRID_COLUMNS_MAX,
COVER_GRID_COLUMNS_MIN,
COVER_GRID_GAP_MAX,
type AlbumEntryObject,
} from '@/lib/config/schema';
import {
IconArrowDown,
IconArrowUp,
@@ -122,6 +127,21 @@ interface Subpage {
grid?: { columns?: number; gap?: number; aspectRatio?: string; layout?: string };
}
/**
* Drops keys the editor cleared so an emptied field never persists as `null`
* in gallery.yaml, and returns undefined once nothing is left — `handleSave`
* only writes `grid` when it is truthy.
*/
function normalizeSubpageGrid(grid: Subpage['grid']): Subpage['grid'] {
if (!grid) return undefined;
const next = { ...grid };
for (const key of Object.keys(next) as Array<keyof typeof next>) {
const value = next[key];
if (value === undefined || value === '') delete next[key];
}
return Object.keys(next).length > 0 ? next : undefined;
}
interface GalleryState {
hero: string[];
albums: AlbumEntry[];
@@ -1452,6 +1472,80 @@ export default function PageBuilder() {
</option>
</select>
</div>
{/* Album cover grid — hidden in essay mode, which
renders a story instead of a cover grid. The
album count is deliberately not checked: it
changes in this very drawer, and a field that
vanishes while you edit is worse than one that
has no effect yet. */}
{sp.grid?.layout !== 'essay' && sp.essayText == null && (
<div className="admin-field" style={{ marginTop: '1rem' }}>
<label>Album Cover Grid</label>
<div style={{ display: 'flex', gap: '12px' }}>
<input
type="number"
min={COVER_GRID_COLUMNS_MIN}
max={COVER_GRID_COLUMNS_MAX}
value={sp.grid?.columns ?? ''}
placeholder="Columns (site default)"
onChange={(e) => {
const raw = e.target.value;
const columns = raw === '' ? undefined : Number(raw);
updateSubpage(spIndex, {
grid: normalizeSubpageGrid({
...(sp.grid || {}),
columns:
columns != null &&
columns >= COVER_GRID_COLUMNS_MIN &&
columns <= COVER_GRID_COLUMNS_MAX
? columns
: undefined,
}),
});
}}
style={{
padding: '8px 12px',
borderRadius: '6px',
flex: 1,
fontSize: '0.9rem',
}}
/>
<input
type="number"
min={0}
max={COVER_GRID_GAP_MAX}
value={sp.grid?.gap ?? ''}
placeholder="Gap in px (theme default)"
onChange={(e) => {
const raw = e.target.value;
const gap = raw === '' ? undefined : Number(raw);
updateSubpage(spIndex, {
grid: normalizeSubpageGrid({
...(sp.grid || {}),
gap:
gap != null && gap >= 0 && gap <= COVER_GRID_GAP_MAX
? gap
: undefined,
}),
});
}}
style={{
padding: '8px 12px',
borderRadius: '6px',
flex: 1,
fontSize: '0.9rem',
}}
/>
</div>
<p className="admin-field-hint">
Overrides how the album covers are tiled on this page. Leave the
column count empty to follow the site-wide grid setting, and the
gap empty to keep the theme&apos;s own spacing. Tablet widths
show at most two covers per row.
</p>
</div>
)}
</div>
{/* Visual Photo Essay Builder (if layout === 'essay') */}