Both pages had a templ render (initial load) and a TypeScript twin (innerHTML rebuild on refresh) of the same fragment. The twins are deleted; the server-rendered markup is now the only markup. - collections: the library switcher swaps in the new books-grid partial (GET /collections/:id/books-grid) instead of re-rendering cards from the /api/collections JSON. Book loading is extracted into Config.loadCollectionBooks, shared verbatim by the page and the partial (smart / dashboard-query / manual branches, family-lens scoping via resolveLibrary + UserVisibleLibraryIDs) so the two cannot drift. - conflicts: resolve/dismiss refreshes swap the new list partial (GET /conflicts/list) with the stats bar as an out-of-band swap, instead of the TS twin — which rendered a degraded card (no checkboxes, no timestamps), pointed at a window.showResolveModal that does not exist, and updated stats via element ids the SSR never had. - shims.d.ts: window.htmx typing (ajax/process) for TS callers. Visibility note: the books-grid partial inherits its family-lens scoping from the shared loader (identical to the detail page); a dedicated hidden-library pin test for the partial route is still worth adding in the next test pass.
23 lines
541 B
TypeScript
23 lines
541 B
TypeScript
declare module "markdown-it-footnote";
|
|
declare module "turndown-plugin-gfm";
|
|
|
|
// htmx is loaded as a classic script on every page and used from TS for
|
|
// partial swaps (rendering-ownership rule: templ renders, JS swaps).
|
|
interface HtmxAjaxOptions {
|
|
target?: string;
|
|
swap?: string;
|
|
values?: Record<string, string>;
|
|
headers?: Record<string, string>;
|
|
}
|
|
|
|
interface Window {
|
|
htmx: {
|
|
ajax(
|
|
method: string,
|
|
url: string,
|
|
options?: HtmxAjaxOptions,
|
|
): Promise<boolean>;
|
|
process(element: Element): void;
|
|
};
|
|
}
|