feat(#79): IMP-51 image_overrides axis (u1~u11 backend stamp+CLI+CSS inject + frontend drag/resize+persistence + tests)
This commit is contained in:
@@ -72,6 +72,18 @@ export function applyPersistedNonFrameOverrides(
|
||||
) {
|
||||
next.zone_sections = { ...persisted.zone_sections };
|
||||
}
|
||||
// IMP-51 (#79) u11 — layer the 5th persisted axis (`image_overrides`) by
|
||||
// the same array / non-object guard the zone_geometries branch uses. The
|
||||
// u3 typed client (services/userOverridesApi.ts) shape and the on-disk
|
||||
// KNOWN_AXES entry (src/user_overrides_io.py u1) are both flat dicts
|
||||
// (image_id → {x,y,w,h} percent-of-slide), so a shallow copy is enough.
|
||||
if (
|
||||
persisted.image_overrides &&
|
||||
typeof persisted.image_overrides === "object" &&
|
||||
!Array.isArray(persisted.image_overrides)
|
||||
) {
|
||||
next.image_overrides = { ...persisted.image_overrides };
|
||||
}
|
||||
return { ...selection, overrides: next };
|
||||
}
|
||||
|
||||
@@ -143,13 +155,17 @@ export function createInitialUserSelection(slidePlan?: SlidePlan | null): UserSe
|
||||
zone_sections: initialSections,
|
||||
zone_sizes: {},
|
||||
zone_geometries: {},
|
||||
// IMP-51 (#79) u11 — image_overrides axis starts empty; entries land
|
||||
// here via `saveImageOverride` (SlideCanvas drag/resize handler) and
|
||||
// are seeded on reopen via `applyPersistedNonFrameOverrides`.
|
||||
image_overrides: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function saveZoneGeometry(
|
||||
selection: UserSelection,
|
||||
zoneId: string,
|
||||
selection: UserSelection,
|
||||
zoneId: string,
|
||||
geometry: { x: number; y: number; w: number; h: number }
|
||||
): UserSelection {
|
||||
return {
|
||||
@@ -164,6 +180,32 @@ export function saveZoneGeometry(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* IMP-51 (#79) u11 — record a single `image_id` → slide-absolute percent
|
||||
* geometry on the in-memory selection. Mirrors `saveZoneGeometry` but on
|
||||
* the 5th persisted axis (`image_overrides`); the SlideCanvas drag/resize
|
||||
* handler (u8) emits one entry per pointer move, and u10's Home wiring
|
||||
* funnels each emit through this helper before scheduling the debounced
|
||||
* PUT. Pure / immutable — returns a fresh `UserSelection`; the input is
|
||||
* never mutated. Existing entries for the same `imageId` are replaced.
|
||||
*/
|
||||
export function saveImageOverride(
|
||||
selection: UserSelection,
|
||||
imageId: string,
|
||||
geometry: { x: number; y: number; w: number; h: number },
|
||||
): UserSelection {
|
||||
return {
|
||||
...selection,
|
||||
overrides: {
|
||||
...selection.overrides,
|
||||
image_overrides: {
|
||||
...selection.overrides.image_overrides,
|
||||
[imageId]: geometry,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function saveZoneSizes(selection: UserSelection, groupId: string, sizes: number[]): UserSelection {
|
||||
return {
|
||||
...selection,
|
||||
|
||||
Reference in New Issue
Block a user