|
|
|
|
@ -1,13 +1,13 @@
|
|
|
|
|
import { untrack } from 'svelte';
|
|
|
|
|
import { createAttrs } from '$uix/morfo';
|
|
|
|
|
import { context, type WithRefOpts } from '../../provider';
|
|
|
|
|
import { type Active, type ActiveProps, type StateProps } from '$libs/reactive';
|
|
|
|
|
import { type ActiveProps, type StateProps } from '$libs/reactive';
|
|
|
|
|
import type { Orientation, Direction, SomaKeyboardEvent, SomaMouseEvent } from '../../types';
|
|
|
|
|
import { KEYS, getDirectionalKeys } from '../../keyboard';
|
|
|
|
|
|
|
|
|
|
import { toolbarMorfo } from '../../../morfo/components/toolbar';
|
|
|
|
|
import { Soma } from '../../core/soma.svelte';
|
|
|
|
|
import type { SomaRuntimePart } from '../../runtime.svelte';
|
|
|
|
|
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
|
|
|
|
|
|
|
|
|
|
const attrs = createAttrs(toolbarMorfo);
|
|
|
|
|
|
|
|
|
|
@ -27,6 +27,8 @@ interface ToolbarOpts
|
|
|
|
|
export class ToolbarProvider {
|
|
|
|
|
readonly opts: ToolbarOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
|
|
|
|
readonly soma: Soma;
|
|
|
|
|
readonly runtime: SomaRuntime;
|
|
|
|
|
static readonly ctx = context<ToolbarProvider>('Toolbar');
|
|
|
|
|
static get(): ToolbarProvider | undefined {
|
|
|
|
|
return this.ctx.getOr(undefined) as ToolbarProvider | undefined;
|
|
|
|
|
@ -44,19 +46,19 @@ export class ToolbarProvider {
|
|
|
|
|
|
|
|
|
|
private constructor(opts: ToolbarOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(toolbarMorfo, {
|
|
|
|
|
props: {
|
|
|
|
|
orientation: () => this.opts.orientation.current
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.part('provider', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
context: ToolbarProvider.ctx,
|
|
|
|
|
syncAttrs: true
|
|
|
|
|
});
|
|
|
|
|
this.soma = Soma.require();
|
|
|
|
|
this.runtime = this.soma.runtime(toolbarMorfo, {
|
|
|
|
|
props: {
|
|
|
|
|
orientation: () => this.opts.orientation.current
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.runtimePart = this.runtime.part('provider', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
context: ToolbarProvider.ctx,
|
|
|
|
|
syncAttrs: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Get all focusable items in the toolbar, scoped to this root. */
|
|
|
|
|
@ -160,14 +162,16 @@ export class ToolbarButtonProvider {
|
|
|
|
|
private constructor(opts: ToolbarButtonOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.provider = ToolbarProvider.require();
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(toolbarMorfo, {
|
|
|
|
|
props: {
|
|
|
|
|
disabled: () => this.opts.disabled.current,
|
|
|
|
|
orientation: () => this.provider.opts.orientation.current
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.part('button', { id: opts.id, ref: opts.ref, owner: this, syncAttrs: true });
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('button', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
props: {
|
|
|
|
|
disabled: () => this.opts.disabled.current,
|
|
|
|
|
orientation: () => this.provider.opts.orientation.current
|
|
|
|
|
},
|
|
|
|
|
owner: this,
|
|
|
|
|
syncAttrs: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
@ -195,13 +199,15 @@ export class ToolbarLinkProvider {
|
|
|
|
|
private constructor(opts: ToolbarLinkOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.provider = ToolbarProvider.require();
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(toolbarMorfo, {
|
|
|
|
|
props: {
|
|
|
|
|
orientation: () => this.provider.opts.orientation.current
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.part('link', { id: opts.id, ref: opts.ref, owner: this, syncAttrs: true });
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('link', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
props: {
|
|
|
|
|
orientation: () => this.provider.opts.orientation.current
|
|
|
|
|
},
|
|
|
|
|
owner: this,
|
|
|
|
|
syncAttrs: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
@ -243,20 +249,17 @@ export class ToolbarGroupProvider {
|
|
|
|
|
private constructor(opts: ToolbarGroupOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.provider = ToolbarProvider.require();
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(toolbarMorfo, {
|
|
|
|
|
props: {
|
|
|
|
|
disabled: () => this.opts.disabled.current,
|
|
|
|
|
orientation: () => this.provider.opts.orientation.current
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.part('group', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
context: ToolbarGroupProvider.ctx,
|
|
|
|
|
syncAttrs: true
|
|
|
|
|
});
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('group', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
props: {
|
|
|
|
|
disabled: () => this.opts.disabled.current,
|
|
|
|
|
orientation: () => this.provider.opts.orientation.current
|
|
|
|
|
},
|
|
|
|
|
owner: this,
|
|
|
|
|
context: ToolbarGroupProvider.ctx,
|
|
|
|
|
syncAttrs: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isItemPressed(value: string): boolean {
|
|
|
|
|
@ -310,17 +313,19 @@ export class ToolbarGroupItemProvider {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.group = ToolbarGroupProvider.require();
|
|
|
|
|
this.provider = this.group.provider;
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(toolbarMorfo, {
|
|
|
|
|
states: {
|
|
|
|
|
on: () => this.isPressed
|
|
|
|
|
},
|
|
|
|
|
props: {
|
|
|
|
|
disabled: () => this.isDisabled,
|
|
|
|
|
orientation: () => this.provider.opts.orientation.current
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.part('group-item', { id: opts.id, ref: opts.ref, owner: this, syncAttrs: true });
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('group-item', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
states: {
|
|
|
|
|
on: () => this.isPressed
|
|
|
|
|
},
|
|
|
|
|
props: {
|
|
|
|
|
disabled: () => this.isDisabled,
|
|
|
|
|
orientation: () => this.provider.opts.orientation.current
|
|
|
|
|
},
|
|
|
|
|
owner: this,
|
|
|
|
|
syncAttrs: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly isPressed = $derived.by(() => this.group.isItemPressed(this.opts.value.current));
|
|
|
|
|
@ -361,13 +366,15 @@ export class ToolbarSeparatorProvider {
|
|
|
|
|
private constructor(opts: ToolbarSeparatorOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.provider = ToolbarProvider.require();
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(toolbarMorfo, {
|
|
|
|
|
props: {
|
|
|
|
|
orientation: () => this.separatorOrientation
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.part('separator', { id: opts.id, ref: opts.ref, owner: this, syncAttrs: true });
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('separator', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
props: {
|
|
|
|
|
orientation: () => this.separatorOrientation
|
|
|
|
|
},
|
|
|
|
|
owner: this,
|
|
|
|
|
syncAttrs: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Separator orientation is perpendicular to toolbar orientation. */
|
|
|
|
|
|