partial toolbar implementation
This commit is contained in:
94
src/lib/Toolbar.svelte
Normal file
94
src/lib/Toolbar.svelte
Normal file
@@ -0,0 +1,94 @@
|
||||
<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}
|
||||
Reference in New Issue
Block a user