Consolidate Soma dropdown menu runtime

active-uix
dev 5 months ago
parent 5581f548cd
commit aa5581121d

@ -36,7 +36,7 @@ import {
import { SafePolygon } from '../../layers/floating/safe-polygon';
import { dropdownMenuMorfo } from '../../../morfo/components/dropdown-menu';
import type { SomaRuntimePart } from '../../runtime.svelte';
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
const attrs = createAttrs(dropdownMenuMorfo);
@ -93,6 +93,8 @@ interface MenuOpts
export class MenuProvider {
readonly opts: MenuOpts;
readonly runtimePart: SomaRuntimePart;
readonly soma: Soma;
readonly runtime: SomaRuntime;
static readonly ctx = context<MenuProvider>('DropdownMenu');
static get(): MenuProvider | undefined {
return this.ctx.getOr(undefined) as MenuProvider | undefined;
@ -105,7 +107,6 @@ export class MenuProvider {
return new MenuProvider(opts);
}
readonly config = Soma.get();
readonly floatingProvider: FloatingProvider;
readonly contentPresence: Presence;
readonly typeahead = new Typeahead();
@ -116,9 +117,14 @@ export class MenuProvider {
private constructor(opts: MenuOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('provider', { id: opts.id, ref: opts.ref, owner: this, context: MenuProvider.ctx });
this.soma = Soma.require();
this.runtime = this.soma.runtime(dropdownMenuMorfo, {});
this.runtimePart = this.runtime.part('provider', {
id: opts.id,
ref: opts.ref,
owner: this,
context: MenuProvider.ctx
});
this.floatingProvider = FloatingProvider.create();
@ -178,10 +184,12 @@ export class MenuTriggerProvider {
private constructor(opts: MenuTriggerOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('trigger', { id: opts.id, ref: opts.ref, owner: this });
this.provider = MenuProvider.require();
this.runtimePart = this.provider.runtime.part('trigger', {
id: opts.id,
ref: opts.ref,
owner: this
});
this.provider.triggerId.current = opts.id.current;
FloatingAnchor.create({
@ -264,17 +272,15 @@ export class MenuContentProvider {
private constructor(opts: MenuContentOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('content', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.provider.setContentRef(el);
}
});
this.provider = MenuProvider.require();
this.runtimePart = this.provider.runtime.part('content', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.provider.setContentRef(el);
}
});
this.provider.contentId.current = opts.id.current;
// Floating
@ -342,7 +348,7 @@ export class MenuContentProvider {
// Text selection
this.textSelection = TextSelection.use({
ref: readableActive(() => opts.ref.current),
dom: Soma.require().dom,
dom: this.provider.soma.dom,
enabled: readableActive(() => this.provider.opts.open.current),
onPointerDown: readableActive(() => () => {}),
onPointerUp: readableActive(() => () => {})
@ -432,9 +438,12 @@ export class MenuArrowProvider {
private constructor(opts: MenuArrowOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('arrow', { id: opts.id, ref: opts.ref, owner: this });
const provider = MenuProvider.require();
this.runtimePart = provider.runtime.part('arrow', {
id: opts.id,
ref: opts.ref,
owner: this
});
this.floatingArrow = FloatingArrow.create(opts);
}
@ -466,10 +475,12 @@ export class MenuItemProvider {
private constructor(opts: MenuItemOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('item', { id: opts.id, ref: opts.ref, owner: this });
this.provider = MenuProvider.require();
this.runtimePart = this.provider.runtime.part('item', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly onclick = (_e: SomaMouseEvent<HTMLElement>) => {
@ -527,9 +538,13 @@ export class MenuGroupProvider {
private constructor(opts: MenuGroupOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('group', { id: opts.id, ref: opts.ref, owner: this, context: MenuGroupProvider.ctx });
const provider = MenuProvider.require();
this.runtimePart = provider.runtime.part('group', {
id: opts.id,
ref: opts.ref,
owner: this,
context: MenuGroupProvider.ctx
});
}
readonly props = $derived.by(() =>
@ -554,9 +569,12 @@ export class MenuGroupHeadingProvider {
private constructor(opts: MenuGroupHeadingOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('group-heading', { id: opts.id, ref: opts.ref, owner: this });
const provider = MenuProvider.require();
this.runtimePart = provider.runtime.part('group-heading', {
id: opts.id,
ref: opts.ref,
owner: this
});
// Register with parent group if available
const group = MenuGroupProvider.get() as MenuGroupProvider | undefined;
if (group) {
@ -582,9 +600,12 @@ export class MenuSeparatorProvider {
private constructor(opts: MenuSeparatorOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('separator', { id: opts.id, ref: opts.ref, owner: this });
const provider = MenuProvider.require();
this.runtimePart = provider.runtime.part('separator', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly props = $derived.by(() =>
@ -657,10 +678,12 @@ export class MenuCheckboxItemProvider {
private constructor(opts: MenuCheckboxItemOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('checkbox-item', { id: opts.id, ref: opts.ref, owner: this });
this.provider = MenuProvider.require();
this.runtimePart = this.provider.runtime.part('checkbox-item', {
id: opts.id,
ref: opts.ref,
owner: this
});
this.group = MenuCheckboxGroupProvider.get();
}
@ -735,7 +758,8 @@ export class MenuRadioGroupProvider {
private constructor(opts: MenuRadioGroupOpts) {
this.opts = opts;
this.runtimePart = Soma.require().runtime(dropdownMenuMorfo, {}).part('radio-group', {
const provider = MenuProvider.require();
this.runtimePart = provider.runtime.part('radio-group', {
id: opts.id,
ref: opts.ref,
owner: this,
@ -776,10 +800,12 @@ export class MenuRadioItemProvider {
private constructor(opts: MenuRadioItemOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('radio-item', { id: opts.id, ref: opts.ref, owner: this });
this.provider = MenuProvider.require();
this.runtimePart = this.provider.runtime.part('radio-item', {
id: opts.id,
ref: opts.ref,
owner: this
});
this.radioGroup = MenuRadioGroupProvider.require();
}
@ -905,17 +931,15 @@ export class MenuSubTriggerProvider {
// A30: register subTriggerRef via `onRefChange` (attachRef fires at
// mount/unmount inside `untrack`), avoiding the `$effect` feedback.
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('sub-trigger', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.sub.subTriggerRef.current = el;
}
});
this.sub = MenuSubProvider.require();
this.runtimePart = this.sub.provider.runtime.part('sub-trigger', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.sub.subTriggerRef.current = el;
}
});
this.sub.subTriggerId.current = opts.id.current;
FloatingAnchor.create({
@ -1032,17 +1056,15 @@ export class MenuSubContentProvider {
private constructor(opts: MenuSubContentOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(dropdownMenuMorfo, {})
.part('sub-content', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.sub.setContentRef(el);
}
});
this.sub = MenuSubProvider.require();
this.runtimePart = this.sub.provider.runtime.part('sub-content', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.sub.setContentRef(el);
}
});
this.sub.contentId.current = opts.id.current;
this.floating = FloatingContent.create({

Loading…
Cancel
Save

Powered by TurnKey Linux.