From cac7e89232a063ee524c6883bdfb659e31dcc6b0 Mon Sep 17 00:00:00 2001 From: dev Date: Fri, 15 May 2026 02:30:13 +0200 Subject: [PATCH] Consolidate Soma virtual list runtimes --- .../grid-list/grid-list-provider.svelte.ts | 46 ++++++++----- .../virtual-grid-provider.svelte.ts | 46 ++++++------- .../virtual-list-provider.svelte.ts | 64 +++++++++---------- 3 files changed, 85 insertions(+), 71 deletions(-) diff --git a/src/uix/soma/components/grid-list/grid-list-provider.svelte.ts b/src/uix/soma/components/grid-list/grid-list-provider.svelte.ts index 10301fcb9..b00714550 100644 --- a/src/uix/soma/components/grid-list/grid-list-provider.svelte.ts +++ b/src/uix/soma/components/grid-list/grid-list-provider.svelte.ts @@ -10,7 +10,7 @@ import { GRID_LIST_LANGS } from './langs'; import type { GridListSelectionMode } from './types'; import { gridListMorfo } from '../../../morfo/components/grid-list'; -import type { SomaRuntimePart } from '../../runtime.svelte'; +import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte'; const attrs = createAttrs(gridListMorfo); @@ -38,6 +38,8 @@ interface GridListOpts export class GridListProvider { readonly opts: GridListOpts; readonly runtimePart: SomaRuntimePart; + readonly soma: Soma; + readonly runtime: SomaRuntime; static readonly ctx = context('GridList'); static get(): GridListProvider | undefined { return this.ctx.getOr(undefined) as GridListProvider | undefined; @@ -50,7 +52,6 @@ export class GridListProvider { return new GridListProvider(opts); } - readonly soma = Soma.get(); readonly field = FieldProvider.get(); private typeaheadBuffer = ''; @@ -60,9 +61,14 @@ export class GridListProvider { private constructor(opts: GridListOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(gridListMorfo, {}) - .part('provider', { id: opts.id, ref: opts.ref, owner: this, context: GridListProvider.ctx }); + this.soma = Soma.require(); + this.runtime = this.soma.runtime(gridListMorfo, {}); + this.runtimePart = this.runtime.part('provider', { + id: opts.id, + ref: opts.ref, + owner: this, + context: GridListProvider.ctx + }); $effect(() => { return () => { @@ -87,13 +93,13 @@ export class GridListProvider { ); readonly resolvedDir: Active = readableActive( - () => this.soma?.prefs.getDir() ?? 'ltr' + () => this.soma.prefs.getDir() ?? 'ltr' ); readonly resolvedAriaLabel: Active = readableActive(() => this.opts.ariaLabelledby.current ? undefined - : this.opts.ariaLabel.current || this.soma?.langs.ts(GRID_LIST_LANGS.LABEL) || undefined + : this.opts.ariaLabel.current || this.soma.langs.ts(GRID_LIST_LANGS.LABEL) || undefined ); readonly isEmpty = $derived.by(() => this.opts.value.current.length === 0); @@ -448,10 +454,12 @@ export class GridListRowProvider { private constructor(opts: GridListRowOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(gridListMorfo, {}) - .part('row', { id: opts.id, ref: opts.ref, owner: this }); this.provider = GridListProvider.require(); + this.runtimePart = this.provider.runtime.part('row', { + id: opts.id, + ref: opts.ref, + owner: this + }); } readonly isSelected = $derived.by(() => this.provider.isSelected(this.opts.value.current)); @@ -508,10 +516,12 @@ export class GridListCellProvider { private constructor(opts: GridListCellOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(gridListMorfo, {}) - .part('cell', { id: opts.id, ref: opts.ref, owner: this }); this.provider = GridListProvider.require(); + this.runtimePart = this.provider.runtime.part('cell', { + id: opts.id, + ref: opts.ref, + owner: this + }); } /** @@ -550,10 +560,12 @@ export class GridListSelectionCheckboxProvider { private constructor(opts: GridListSelectionCheckboxOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(gridListMorfo, {}) - .part('selection-checkbox', { id: opts.id, ref: opts.ref, owner: this }); this.provider = GridListProvider.require(); + this.runtimePart = this.provider.runtime.part('selection-checkbox', { + id: opts.id, + ref: opts.ref, + owner: this + }); } /** Read the enclosing row's value lazily (on click). */ @@ -579,7 +591,7 @@ export class GridListSelectionCheckboxProvider { readonly resolvedAriaLabel = $derived.by( () => this.opts.ariaLabel.current || - this.provider.soma?.langs.ts(GRID_LIST_LANGS.SELECT_ROW) || + this.provider.soma.langs.ts(GRID_LIST_LANGS.SELECT_ROW) || undefined ); diff --git a/src/uix/soma/components/virtual-grid/virtual-grid-provider.svelte.ts b/src/uix/soma/components/virtual-grid/virtual-grid-provider.svelte.ts index 977a83eb7..0f3623a1a 100644 --- a/src/uix/soma/components/virtual-grid/virtual-grid-provider.svelte.ts +++ b/src/uix/soma/components/virtual-grid/virtual-grid-provider.svelte.ts @@ -4,7 +4,7 @@ import type { ScrollToCellOptions, VirtualCell } from './types'; import { virtualGridMorfo } from '../../../morfo/components/virtual-grid'; import { Soma } from '../../core/soma.svelte'; -import type { SomaRuntimePart } from '../../runtime.svelte'; +import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte'; // ── Helpers (1D per-axis) ────────────────────────────────────────────────── @@ -74,6 +74,8 @@ interface VirtualGridOpts export class VirtualGridProvider { readonly opts: VirtualGridOpts; readonly runtimePart: SomaRuntimePart; + readonly soma: Soma; + readonly runtime: SomaRuntime; static readonly ctx = context('VirtualGrid'); static get(): VirtualGridProvider | undefined { return this.ctx.getOr(undefined) as VirtualGridProvider | undefined; @@ -94,14 +96,14 @@ export class VirtualGridProvider { private constructor(opts: VirtualGridOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(virtualGridMorfo, {}) - .part('provider', { - id: opts.id, - ref: opts.ref, - owner: this, - context: VirtualGridProvider.ctx - }); + this.soma = Soma.require(); + this.runtime = this.soma.runtime(virtualGridMorfo, {}); + this.runtimePart = this.runtime.part('provider', { + id: opts.id, + ref: opts.ref, + owner: this, + context: VirtualGridProvider.ctx + }); } readonly totalHeight = $derived.by(() => this.opts.rowCount.current * this.opts.rowSize.current); @@ -214,17 +216,15 @@ export class VirtualGridViewportProvider { private constructor(opts: VirtualGridViewportOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(virtualGridMorfo, {}) - .part('viewport', { - id: opts.id, - ref: opts.ref, - owner: this, - onRefChange: (el) => { - this.provider.viewportRef = el; - } - }); this.provider = VirtualGridProvider.require(); + this.runtimePart = this.provider.runtime.part('viewport', { + id: opts.id, + ref: opts.ref, + owner: this, + onRefChange: (el) => { + this.provider.viewportRef = el; + } + }); $effect(() => { const el = this.opts.ref.current; @@ -290,10 +290,12 @@ export class VirtualGridCellProvider { private constructor(opts: VirtualGridCellOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(virtualGridMorfo, {}) - .part('cell', { id: opts.id, ref: opts.ref, owner: this }); this.provider = VirtualGridProvider.require(); + this.runtimePart = this.provider.runtime.part('cell', { + id: opts.id, + ref: opts.ref, + owner: this + }); } readonly props = $derived.by(() => { diff --git a/src/uix/soma/components/virtual-list/virtual-list-provider.svelte.ts b/src/uix/soma/components/virtual-list/virtual-list-provider.svelte.ts index 1f222b36b..866f0ae04 100644 --- a/src/uix/soma/components/virtual-list/virtual-list-provider.svelte.ts +++ b/src/uix/soma/components/virtual-list/virtual-list-provider.svelte.ts @@ -6,7 +6,7 @@ import type { ScrollToIndexOptions, VirtualItem } from './types'; import { virtualListMorfo } from '../../../morfo/components/virtual-list'; import { Soma } from '../../core/soma.svelte'; -import type { SomaRuntimePart } from '../../runtime.svelte'; +import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte'; // ── Root provider ────────────────────────────────────────────────────────── @@ -26,6 +26,8 @@ interface VirtualListOpts export class VirtualListProvider { readonly opts: VirtualListOpts; readonly runtimePart: SomaRuntimePart; + readonly soma: Soma; + readonly runtime: SomaRuntime; static readonly ctx = context('VirtualList'); static get(): VirtualListProvider | undefined { return this.ctx.getOr(undefined) as VirtualListProvider | undefined; @@ -65,14 +67,14 @@ export class VirtualListProvider { private constructor(opts: VirtualListOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(virtualListMorfo, {}) - .part('provider', { - id: opts.id, - ref: opts.ref, - owner: this, - context: VirtualListProvider.ctx - }); + this.soma = Soma.require(); + this.runtime = this.soma.runtime(virtualListMorfo, {}); + this.runtimePart = this.runtime.part('provider', { + id: opts.id, + ref: opts.ref, + owner: this, + context: VirtualListProvider.ctx + }); } readonly isHorizontal = $derived.by(() => this.opts.orientation.current === 'horizontal'); @@ -308,17 +310,15 @@ export class VirtualListViewportProvider { private constructor(opts: VirtualListViewportOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(virtualListMorfo, {}) - .part('viewport', { - id: opts.id, - ref: opts.ref, - owner: this, - onRefChange: (el) => { - this.provider.viewportRef = el; - } - }); this.provider = VirtualListProvider.require(); + this.runtimePart = this.provider.runtime.part('viewport', { + id: opts.id, + ref: opts.ref, + owner: this, + onRefChange: (el) => { + this.provider.viewportRef = el; + } + }); $effect(() => { const el = this.opts.ref.current; @@ -383,17 +383,15 @@ export class VirtualListWindowViewportProvider { private constructor(opts: VirtualListWindowViewportOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(virtualListMorfo, {}) - .part('window-viewport', { - id: opts.id, - ref: opts.ref, - owner: this, - onRefChange: (el) => { - this.provider.windowHostRef = el; - } - }); this.provider = VirtualListProvider.require(); + this.runtimePart = this.provider.runtime.part('window-viewport', { + id: opts.id, + ref: opts.ref, + owner: this, + onRefChange: (el) => { + this.provider.windowHostRef = el; + } + }); $effect(() => { const el = this.opts.ref.current; @@ -460,10 +458,12 @@ export class VirtualListItemProvider { private constructor(opts: VirtualListItemOpts) { this.opts = opts; - this.runtimePart = Soma.require() - .runtime(virtualListMorfo, {}) - .part('item', { id: opts.id, ref: opts.ref, owner: this }); this.provider = VirtualListProvider.require(); + this.runtimePart = this.provider.runtime.part('item', { + id: opts.id, + ref: opts.ref, + owner: this + }); // ResizeObserver: report real rendered size back to the provider so // the cache reflects actual layout. Only attaches when the consumer