You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
54 lines
1.3 KiB
54 lines
1.3 KiB
<script lang="ts" context="module">
|
|
import { getContext, setContext } from "svelte";
|
|
import { writable, type Readable } from "svelte/store";
|
|
import { getStateContext } from "./StateContext.svelte";
|
|
|
|
const ctxKey = {ctx: "SelectContext"};
|
|
|
|
export interface SelectContextData {
|
|
toggleSelection(id: string): void
|
|
selectedList: Readable<string[]>
|
|
selectedMap: Readable<{[id:string]: boolean}>
|
|
}
|
|
|
|
export function getSelectedContext(): SelectContextData {
|
|
return getContext(ctxKey) as SelectContextData;
|
|
}
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
const selectedList = writable<string[]>([]);
|
|
const selectedMap = writable<{[id:string]: boolean}>({});
|
|
|
|
const {state} = getStateContext();
|
|
|
|
function toggleSelection(id: string) {
|
|
selectedMap.update(m => ({...m, [id]: !m[id]}));
|
|
}
|
|
|
|
// Effect: remove non-existent devices
|
|
$: {
|
|
const newMap = {...$selectedMap};
|
|
for (const id in newMap) {
|
|
if (!Object.hasOwn(newMap, id)) {
|
|
continue;
|
|
}
|
|
if (!$state?.devices[id]) {
|
|
delete newMap[id];
|
|
}
|
|
}
|
|
|
|
$selectedMap = newMap;
|
|
}
|
|
|
|
// Effect: sync list
|
|
$: $selectedList = Object.keys($selectedMap).filter(id => !!$selectedMap[id]);
|
|
|
|
setContext(ctxKey, {
|
|
selectedList: {subscribe: selectedList.subscribe},
|
|
selectedMap: {subscribe: selectedMap.subscribe},
|
|
toggleSelection,
|
|
});
|
|
</script>
|
|
|
|
<slot></slot>
|