Skip to content

Instantly share code, notes, and snippets.

@stephane-vanraes
Created September 13, 2023 08:41
Show Gist options
  • Save stephane-vanraes/cbae87b6889f44b5e6fde45053146a94 to your computer and use it in GitHub Desktop.
Save stephane-vanraes/cbae87b6889f44b5e6fde45053146a94 to your computer and use it in GitHub Desktop.
Svelte DrawerStore
<script context="module" lang="ts">
import { get, writable } from 'svelte/store';
import { onDestroy } from 'svelte';
import type { ComponentProps, ComponentType, SvelteComponent } from 'svelte';
type DrawerStoreItem = {
component: ComponentType;
props: Record<string, unknown>;
};
type DrawerStore = <T extends SvelteComponent>(
component: ComponentType<T>,
props: ComponentProps<T>
) => <U extends SvelteComponent>(component: ComponentType<U>, props: ComponentProps<U>) => void;
// Internal Store
const store = writable<DrawerStoreItem[]>([]);
// Function to set and update store
export const drawerStore: DrawerStore = (component, props) => {
// Get the index where we will inject this new item
const index = get(store).length;
// Inject the given item
store.update(($store) => ($store.push({ component, props }), $store));
// This kind of assumes that if you destroy this you will also remove all items under it
onDestroy(() => store.update(($store) => ($store.pop(), $store)));
// Return a function that allows to update the drawer "in place"
return (component, props) =>
store.update(($store) => (($store[index] = { component, props }), $store));
};
</script>
{#if $store.length > 0}
<svelte:component
this={$store[$store.length - 1].component}
{...$store[$store.length - 1].props}
/>
{/if}
<script>
import { drawerStore } from '$lib/components/Drawer.svelte';
import MyDrawer from './MyDrawer.svelte';
// just pop it in thre
drawerStore(MyDrawer, { name: 'Rainlife' });
</script>
<script>
import { drawerStore } from '$lib/components/Drawer.svelte';
import MyDrawer from './MyDrawer.svelte';
// the data from a load function, it just returns the slug here
export let data;
// take the returned function because we want to update without adding more elements to the stack
const updateDrawer = drawerStore(MyDrawer, { slug: data.slug });
// update the drawer when the slug changes
$: updateDrawer(MyDrawer, { slug: data.slug });
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment