<script lang="ts" module>
	type ToolbarRenderable<P extends unknown[] = any[]> =
		| { type: 'component'; component: Component; props?: P }
		| { type: 'snippet'; snippet: Snippet<P>; props?: P }
		| { type: 'string'; value: string };

	interface ToolbarButton<P extends unknown[] = any[]> {
		type: 'toggle' | 'button';
		title: string;
		render: ToolbarRenderable<P>;
	}

	interface ToolbarDivider {
		type: 'divider';
	}

	interface ToolbarGroup {
		type: 'group';
		items: ToolbarItem[];
	}

	export type ToolbarItem = ToolbarButton<any> | ToolbarDivider | ToolbarGroup;

	type SnippetArgs<T> = T extends Snippet<infer Args extends unknown[]> ? Args : never;

	// For snippet-based buttons
	export function toolbarItem<S extends Snippet<any>>(item: {
		type: 'button' | 'toggle';
		title: string;
		render: {
			type: 'snippet';
			snippet: S;
			props: SnippetArgs<S>;
		};
	}): typeof item;

	// For component-based buttons (optional, for completeness)
	export function toolbarItem<C extends Component>(item: {
		type: 'button' | 'toggle';
		title: string;
		render: {
			type: 'component';
			component: C;
			props: ComponentProps<C>;
		};
	}): typeof item;

	// For other items (divider, group, etc)
	export function toolbarItem<T extends ToolbarDivider | ToolbarGroup>(item: T): T;

	// Implementation
	export function toolbarItem(item: any): any {
		return item;
	}
</script>

<script lang="ts">
	import { type Component, type Snippet, type ComponentProps } from 'svelte';

	interface Props {
		items: ToolbarItem[];
	}

	let { items }: Props = $props();
</script>

<div>
	{#each items as toolbarItem}
		{@render item(toolbarItem)}
	{/each}
</div>

{#snippet item(i: ToolbarItem)}
	{#if i.type === 'button' || i.type === 'toggle'}
		<button class="toolbar-button">
			{#if i.render.type === 'component'}
				<item.render.component {...i.render.props} />
			{:else if i.render.type === 'snippet'}
				{@render i.render.snippet(i.render.props)}
			{:else if i.render.type === 'string'}
				<span>{i.render.value}</span>
			{/if}
			<span>{i.title}</span>
		</button>
	{:else if i.type === 'divider'}
		<hr class="toolbar-divider" />
	{:else if i.type === 'group'}
		<div class="toolbar-group">
			{#each i.items as groupItem}
				{@render item(groupItem)}
			{/each}
		</div>
	{/if}
{/snippet}
