Browse Source

Use a reactive map to make ToC entry expansion react on click

master
buttercat1791 9 months ago
parent
commit
44a9d282a5
  1. 13
      src/lib/components/publications/TableOfContents.svelte
  2. 8
      src/lib/components/publications/table_of_contents.svelte.ts

13
src/lib/components/publications/TableOfContents.svelte

@ -32,17 +32,13 @@
return newEntries; return newEntries;
}); });
function getEntryExpanded(address: string) {
return toc.getEntry(address)?.expanded;
}
function setEntryExpanded(address: string, expanded: boolean = false) { function setEntryExpanded(address: string, expanded: boolean = false) {
const entry = toc.getEntry(address); const entry = toc.getEntry(address);
if (!entry) { if (!entry) {
return; return;
} }
entry.expanded = expanded; toc.expandedMap.set(address, expanded);
entry.resolveChildren(); entry.resolveChildren();
} }
@ -57,9 +53,10 @@
<Accordion multiple> <Accordion multiple>
{#each entries as entry} {#each entries as entry}
{@const address = entry.address} {@const address = entry.address}
{@const expanded = toc.expandedMap.get(address) ?? false}
<AccordionItem <AccordionItem
bind:open={ bind:open={
() => getEntryExpanded(address), () => expanded,
(open) => setEntryExpanded(address, open) (open) => setEntryExpanded(address, open)
} }
> >
@ -82,8 +79,8 @@
<!-- TODO: Clicks on entries aren't reactive. --> <!-- TODO: Clicks on entries aren't reactive. -->
{#each entries as entry} {#each entries as entry}
{@const address = entry.address} {@const address = entry.address}
{@const expanded = toc.expandedMap.get(address) ?? false}
{#if entry.children.length > 0} {#if entry.children.length > 0}
{@const expanded = getEntryExpanded(address)}
{@const childDepth = depth + 1} {@const childDepth = depth + 1}
<SidebarDropdownWrapper <SidebarDropdownWrapper
label={entry.title} label={entry.title}
@ -103,7 +100,7 @@
<!-- TODO: Add href --> <!-- TODO: Add href -->
<SidebarItem <SidebarItem
label={entry.title} label={entry.title}
onclick={() => handleEntryClick(address, !getEntryExpanded(address))} onclick={() => handleEntryClick(address, !expanded)}
/> />
{/if} {/if}
{/each} {/each}

8
src/lib/components/publications/table_of_contents.svelte.ts

@ -10,7 +10,6 @@ export interface TocEntry {
children: TocEntry[]; children: TocEntry[];
parent?: TocEntry; parent?: TocEntry;
depth: number; depth: number;
expanded: boolean;
childrenResolved: boolean; childrenResolved: boolean;
resolveChildren: () => Promise<void>; resolveChildren: () => Promise<void>;
} }
@ -24,7 +23,8 @@ export interface TocEntry {
*/ */
export class TableOfContents { export class TableOfContents {
public addressMap: SvelteMap<string, TocEntry> = new SvelteMap(); public addressMap: SvelteMap<string, TocEntry> = new SvelteMap();
public expandedMap: SvelteMap<string, boolean> = new SvelteMap();
#root: TocEntry | null = null; #root: TocEntry | null = null;
#publicationTree: SveltePublicationTree; #publicationTree: SveltePublicationTree;
#pagePathname: string; #pagePathname: string;
@ -92,11 +92,11 @@ export class TableOfContents {
href, href,
depth, depth,
children: [], children: [],
expanded: false,
childrenResolved: true, childrenResolved: true,
resolveChildren: () => Promise.resolve(), resolveChildren: () => Promise.resolve(),
}; };
parentEntry.children.push(tocEntry); parentEntry.children.push(tocEntry);
this.expandedMap.set(tocEntry.address, false);
this.buildTocFromDocument(header, tocEntry, depth + 1); this.buildTocFromDocument(header, tocEntry, depth + 1);
} }
@ -213,10 +213,10 @@ export class TableOfContents {
href: `${this.#pagePathname}#${address}`, href: `${this.#pagePathname}#${address}`,
children: [], children: [],
depth, depth,
expanded: false,
childrenResolved: false, childrenResolved: false,
resolveChildren: resolver, resolveChildren: resolver,
}; };
this.expandedMap.set(address, false);
return entry; return entry;
} }

Loading…
Cancel
Save