Consolidate Soma command runtime

active-uix
dev 5 months ago
parent c4c37a3719
commit 3097a209f0

@ -19,7 +19,7 @@ import { computeCommandScore } from './score';
import type { CommandFilterFn, CommandSnippetProps } from './types';
import { commandMorfo } from '../../../morfo/components/command';
import type { SomaRuntimePart } from '../../runtime.svelte';
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
// ── Registry shapes ──────────────────────────────────────────────────────────
@ -90,6 +90,8 @@ interface CommandOpts
export class CommandProvider {
readonly opts: CommandOpts;
readonly runtimePart: SomaRuntimePart;
readonly soma: Soma;
readonly runtime: SomaRuntime;
static readonly ctx = context<CommandProvider>('Command');
static get(): CommandProvider | undefined {
return this.ctx.getOr(undefined) as CommandProvider | undefined;
@ -102,8 +104,6 @@ export class CommandProvider {
return new CommandProvider(opts);
}
readonly soma = Soma.get();
/**
* Plain storage + a version counter that increments synchronously on each
* mutation. Synchronous = consumer event handlers (clicks) see up-to-date
@ -123,9 +123,14 @@ export class CommandProvider {
private constructor(opts: CommandOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('provider', { id: opts.id, ref: opts.ref, owner: this, context: CommandProvider.ctx });
this.soma = Soma.require();
this.runtime = this.soma.runtime(commandMorfo, {});
this.runtimePart = this.runtime.part('provider', {
id: opts.id,
ref: opts.ref,
owner: this,
context: CommandProvider.ctx
});
dbg('Provider.ctor');
// Build the stable snippet props object. Getters read reactive state
@ -413,10 +418,12 @@ export class CommandInputProvider {
private constructor(opts: CommandInputOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('input', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CommandProvider.require();
this.runtimePart = this.provider.runtime.part('input', {
id: opts.id,
ref: opts.ref,
owner: this
});
this.provider.inputId.current = opts.id.current;
}
@ -524,10 +531,12 @@ export class CommandListProvider {
private constructor(opts: CommandListOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('list', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CommandProvider.require();
this.runtimePart = this.provider.runtime.part('list', {
id: opts.id,
ref: opts.ref,
owner: this
});
this.provider.listId.current = opts.id.current;
}
@ -536,7 +545,7 @@ export class CommandListProvider {
...this.runtimePart.props,
role: 'listbox' as const,
'aria-label':
this.provider.opts.label.current ?? this.provider.soma?.langs.ts(COMMAND_LANGS.LIST)
this.provider.opts.label.current ?? this.provider.soma.langs.ts(COMMAND_LANGS.LIST)
} as const)
);
}
@ -556,9 +565,12 @@ export class CommandViewportProvider {
private constructor(opts: CommandViewportOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('viewport', { id: opts.id, ref: opts.ref, owner: this });
const provider = CommandProvider.require();
this.runtimePart = provider.runtime.part('viewport', {
id: opts.id,
ref: opts.ref,
owner: this
});
$effect(() => {
const el = opts.ref.current;
@ -606,11 +618,13 @@ export class CommandItemProvider {
private constructor(opts: CommandItemOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('item', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CommandProvider.require();
this.group = CommandGroupProvider.get();
this.runtimePart = this.provider.runtime.part('item', {
id: opts.id,
ref: opts.ref,
owner: this
});
dbg('Item.ctor', opts.value.current);
const groupValue = this.group?.opts.value.current;
@ -730,11 +744,13 @@ export class CommandLinkItemProvider {
private constructor(opts: CommandLinkItemOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('link-item', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CommandProvider.require();
this.group = CommandGroupProvider.get();
this.runtimePart = this.provider.runtime.part('link-item', {
id: opts.id,
ref: opts.ref,
owner: this
});
const groupValue = this.group?.opts.value.current;
// See the matching block in CommandItemProvider: register once per
@ -842,15 +858,13 @@ export class CommandGroupProvider {
private constructor(opts: CommandGroupOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('group', {
id: opts.id,
ref: opts.ref,
owner: this,
context: CommandGroupProvider.ctx
});
this.provider = CommandProvider.require();
this.runtimePart = this.provider.runtime.part('group', {
id: opts.id,
ref: opts.ref,
owner: this,
context: CommandGroupProvider.ctx
});
// Register ONCE per group identity. The register/unregister calls read
// from the reactive `groups` array internally, so wrap in untrack to
@ -894,10 +908,12 @@ export class CommandGroupHeadingProvider {
private constructor(opts: CommandGroupHeadingOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('group-heading', { id: opts.id, ref: opts.ref, owner: this });
this.group = CommandGroupProvider.require();
this.runtimePart = this.group.provider.runtime.part('group-heading', {
id: opts.id,
ref: opts.ref,
owner: this
});
this.group.headingId.current = opts.id.current;
}
@ -919,10 +935,12 @@ export class CommandGroupItemsProvider {
private constructor(opts: CommandGroupItemsOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('group-items', { id: opts.id, ref: opts.ref, owner: this });
CommandGroupProvider.require();
const group = CommandGroupProvider.require();
this.runtimePart = group.provider.runtime.part('group-items', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly props = $derived.by(() =>
@ -948,10 +966,12 @@ export class CommandEmptyProvider {
private constructor(opts: CommandEmptyOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('empty', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CommandProvider.require();
this.runtimePart = this.provider.runtime.part('empty', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly shouldRender = $derived.by(() => this.provider.isEmpty);
@ -978,10 +998,12 @@ export class CommandLoadingProvider {
private constructor(opts: CommandLoadingOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('loading', { id: opts.id, ref: opts.ref, owner: this });
CommandProvider.require();
const provider = CommandProvider.require();
this.runtimePart = provider.runtime.part('loading', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly percent: Active<number | undefined> = readableActive(() => {
@ -1017,10 +1039,12 @@ export class CommandSeparatorProvider {
private constructor(opts: CommandSeparatorOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(commandMorfo, {})
.part('separator', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CommandProvider.require();
this.runtimePart = this.provider.runtime.part('separator', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
/** Hide the separator when the palette has no visible items, unless forced. */

Loading…
Cancel
Save

Powered by TurnKey Linux.