Consolidate Soma calendar runtime

active-uix
dev 5 months ago
parent e1df915add
commit 8618703d31

@ -42,7 +42,7 @@ import type {
// ── Contract ─────────────────────────────────────────────────────────────────
import { calendarMorfo } from '../../../morfo/components/calendar';
import type { SomaRuntimePart } from '../../runtime.svelte';
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
const attrs = createAttrs(calendarMorfo);
@ -107,6 +107,8 @@ export function resolveInitialCalendarPlaceholder(
export class CalendarProvider {
readonly opts: CalendarOpts;
readonly runtimePart: SomaRuntimePart;
readonly soma: Soma;
readonly runtime: SomaRuntime;
static readonly ctx = context<CalendarProvider>('Calendar');
static get(): CalendarProvider | undefined {
return this.ctx.getOr(undefined) as CalendarProvider | undefined;
@ -118,8 +120,6 @@ export class CalendarProvider {
return new CalendarProvider(opts);
}
readonly soma = Soma.get();
/** Child ids exposed so the Grid can wire aria-labelledby. */
headingId = state('');
/** Live-region text for announcements. */
@ -127,9 +127,14 @@ export class CalendarProvider {
private constructor(opts: CalendarOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('provider', { id: opts.id, ref: opts.ref, owner: this, context: CalendarProvider.ctx });
this.soma = Soma.require();
this.runtime = this.soma.runtime(calendarMorfo, {});
this.runtimePart = this.runtime.part('provider', {
id: opts.id,
ref: opts.ref,
owner: this,
context: CalendarProvider.ctx
});
// Initial focus management used to live in the wrapper. Move it here so
// the wrapper stays thin and the focus contract is centralized.
@ -147,7 +152,7 @@ export class CalendarProvider {
// ── Derived reactive model ────────────────────────────────────────────────
readonly effectiveLocale = $derived.by(
() => this.opts.locale.current || this.soma?.langs.getLocale() || 'en'
() => this.opts.locale.current || this.soma.langs.getLocale() || 'en'
);
readonly months: Month<DateValue>[] = $derived.by(() =>
@ -175,7 +180,7 @@ export class CalendarProvider {
);
readonly dateOrder: DateOrder = $derived.by(() => {
return (this.soma?.dates?.getDateOrder?.() ?? 'DMY') as DateOrder;
return (this.soma.dates?.getDateOrder?.() ?? 'DMY') as DateOrder;
});
/**
@ -216,7 +221,7 @@ export class CalendarProvider {
readonly fullCalendarLabel = $derived.by(() => {
const base =
this.opts.calendarLabel.current ?? this.soma?.langs.ts(CALENDAR_LANGS.LABEL) ?? 'Calendar';
this.opts.calendarLabel.current ?? this.soma.langs.ts(CALENDAR_LANGS.LABEL) ?? 'Calendar';
return `${base}, ${this.headingValue}`;
});
@ -444,10 +449,12 @@ export class CalendarHeaderProvider {
private constructor(opts: WithRefOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('header', { id: opts.id, ref: opts.ref, owner: this });
CalendarProvider.require();
const provider = CalendarProvider.require();
this.runtimePart = provider.runtime.part('header', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly props = $derived.by(() =>
@ -468,10 +475,12 @@ export class CalendarHeadingProvider {
private constructor(opts: WithRefOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('heading', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CalendarProvider.require();
this.runtimePart = this.provider.runtime.part('heading', {
id: opts.id,
ref: opts.ref,
owner: this
});
this.provider.headingId.current = opts.id.current;
}
@ -494,10 +503,12 @@ abstract class CalendarPaginationButtonProvider {
protected constructor(opts: WithRefOpts, part: 'prev-button' | 'next-button', labelRef: string) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part(part, { id: opts.id, ref: opts.ref, owner: this });
this.provider = CalendarProvider.require();
this.runtimePart = this.provider.runtime.part(part, {
id: opts.id,
ref: opts.ref,
owner: this
});
this.labelRef = labelRef;
}
@ -511,7 +522,7 @@ abstract class CalendarPaginationButtonProvider {
return this.runtimePart.assert({
...this.runtimePart.props,
type: 'button' as const,
'aria-label': this.provider.soma?.langs.ts(this.labelRef),
'aria-label': this.provider.soma.langs.ts(this.labelRef),
'aria-disabled': boolToStr(disabled),
'data-disabled': boolToEmptyStrOrUndef(disabled),
disabled,
@ -572,10 +583,12 @@ export class CalendarMonthSelectProvider {
private constructor(opts: CalendarMonthSelectOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('month-select', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CalendarProvider.require();
this.runtimePart = this.provider.runtime.part('month-select', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly monthItems: CalendarMonthSelectSnippetProps['monthItems'] = $derived.by(() => {
@ -611,7 +624,7 @@ export class CalendarMonthSelectProvider {
const disabled = this.opts.disabled.current || this.provider.opts.disabled.current;
return this.runtimePart.assert({
...this.runtimePart.props,
'aria-label': this.provider.soma?.langs.ts(CALENDAR_LANGS.MONTH_SELECT),
'aria-label': this.provider.soma.langs.ts(CALENDAR_LANGS.MONTH_SELECT),
'aria-disabled': boolToStr(disabled),
'data-disabled': boolToEmptyStrOrUndef(disabled),
disabled,
@ -643,10 +656,12 @@ export class CalendarYearSelectProvider {
private constructor(opts: CalendarYearSelectOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('year-select', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CalendarProvider.require();
this.runtimePart = this.provider.runtime.part('year-select', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly yearItems: CalendarYearSelectSnippetProps['yearItems'] = $derived.by(() => {
@ -682,7 +697,7 @@ export class CalendarYearSelectProvider {
const disabled = this.opts.disabled.current || this.provider.opts.disabled.current;
return this.runtimePart.assert({
...this.runtimePart.props,
'aria-label': this.provider.soma?.langs.ts(CALENDAR_LANGS.YEAR_SELECT),
'aria-label': this.provider.soma.langs.ts(CALENDAR_LANGS.YEAR_SELECT),
'aria-disabled': boolToStr(disabled),
'data-disabled': boolToEmptyStrOrUndef(disabled),
disabled,
@ -705,10 +720,12 @@ export class CalendarGridProvider {
private constructor(opts: WithRefOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('grid', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CalendarProvider.require();
this.runtimePart = this.provider.runtime.part('grid', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly props = $derived.by(() => {
@ -731,10 +748,12 @@ export class CalendarGridHeadProvider {
}
private constructor(opts: WithRefOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('grid-head', { id: opts.id, ref: opts.ref, owner: this });
CalendarProvider.require();
const provider = CalendarProvider.require();
this.runtimePart = provider.runtime.part('grid-head', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly props = $derived.by(() =>
this.runtimePart.assert({ ...this.runtimePart.props } as const)
@ -749,10 +768,12 @@ export class CalendarGridBodyProvider {
}
private constructor(opts: WithRefOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('grid-body', { id: opts.id, ref: opts.ref, owner: this });
CalendarProvider.require();
const provider = CalendarProvider.require();
this.runtimePart = provider.runtime.part('grid-body', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly props = $derived.by(() =>
this.runtimePart.assert({ ...this.runtimePart.props } as const)
@ -767,10 +788,12 @@ export class CalendarGridRowProvider {
}
private constructor(opts: WithRefOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('grid-row', { id: opts.id, ref: opts.ref, owner: this });
CalendarProvider.require();
const provider = CalendarProvider.require();
this.runtimePart = provider.runtime.part('grid-row', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly props = $derived.by(() =>
this.runtimePart.assert({ ...this.runtimePart.props, role: 'row' as const } as const)
@ -785,10 +808,12 @@ export class CalendarHeadCellProvider {
}
private constructor(opts: WithRefOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('head-cell', { id: opts.id, ref: opts.ref, owner: this });
CalendarProvider.require();
const provider = CalendarProvider.require();
this.runtimePart = provider.runtime.part('head-cell', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly props = $derived.by(() =>
this.runtimePart.assert({ ...this.runtimePart.props, scope: 'col' as const } as const)
@ -818,10 +843,13 @@ export class CalendarCellProvider {
private constructor(opts: CalendarCellOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('cell', { id: opts.id, ref: opts.ref, owner: this, context: CalendarCellProvider.ctx });
this.provider = CalendarProvider.require();
this.runtimePart = this.provider.runtime.part('cell', {
id: opts.id,
ref: opts.ref,
owner: this,
context: CalendarCellProvider.ctx
});
}
readonly flags = $derived.by(() => this.provider.computeFlags(this.opts.date.current));
@ -880,11 +908,13 @@ export class CalendarDayProvider {
private constructor(opts: WithRefOpts) {
this.opts = opts;
this.runtimePart = Soma.require()
.runtime(calendarMorfo, {})
.part('day', { id: opts.id, ref: opts.ref, owner: this });
this.provider = CalendarProvider.require();
this.cell = CalendarCellProvider.require();
this.runtimePart = this.provider.runtime.part('day', {
id: opts.id,
ref: opts.ref,
owner: this
});
}
readonly focused = $derived.by(() =>

Loading…
Cancel
Save

Powered by TurnKey Linux.