diff --git a/src/uix/soma/components/calendar/calendar-provider.svelte.ts b/src/uix/soma/components/calendar/calendar-provider.svelte.ts index 979ce4b5a..bc3bfabfa 100644 --- a/src/uix/soma/components/calendar/calendar-provider.svelte.ts +++ b/src/uix/soma/components/calendar/calendar-provider.svelte.ts @@ -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('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[] = $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(() =>