anki/ts/components/Section.svelte

66 lines
2.3 KiB
Svelte

<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="typescript">
import { setContext } from "svelte";
import { writable } from "svelte/store";
import SectionItem from "./SectionItem.svelte";
import { sectionKey } from "./contextKeys";
import type { Identifier } from "./identifier";
import { insertElement, appendElement } from "./identifier";
import type { SvelteComponent, Registration } from "./registration";
import { makeInterface } from "./registration";
export let id: string | undefined = undefined;
let className: string = "";
export { className as class };
function makeRegistration(): Registration {
const detach = writable(false);
return { detach };
}
const { registerComponent, dynamicItems, getDynamicInterface } =
makeInterface(makeRegistration);
setContext(sectionKey, registerComponent);
export let api: Record<string, never> | undefined = undefined;
let sectionRef: HTMLDivElement;
$: if (sectionRef && api) {
const { addComponent, updateRegistration } = getDynamicInterface(sectionRef);
const insert = (group: SvelteComponent, position: Identifier = 0) =>
addComponent(group, (added, parent) =>
insertElement(added, parent, position)
);
const append = (group: SvelteComponent, position: Identifier = -1) =>
addComponent(group, (added, parent) =>
appendElement(added, parent, position)
);
const show = (id: Identifier) =>
updateRegistration(({ detach }) => detach.set(false), id);
const hide = (id: Identifier) =>
updateRegistration(({ detach }) => detach.set(true), id);
const toggle = (id: Identifier) =>
updateRegistration(
({ detach }) => detach.update((old: boolean): boolean => !old),
id
);
Object.assign(api, { insert, append, show, hide, toggle });
}
</script>
<div bind:this={sectionRef} {id} class={`container mb-1 ${className}`}>
<slot />
{#each $dynamicItems as item}
<SectionItem id={item[0].id} registration={item[1]}>
<svelte:component this={item[0].component} {...item[0].props} />
</SectionItem>
{/each}
</div>