Consolidate Soma overlay runtimes

active-uix
dev 5 months ago
parent cac7e89232
commit c7527fc107

@ -19,7 +19,7 @@ import {
import { linkPreviewMorfo } from '../../../morfo/components/link-preview'; import { linkPreviewMorfo } from '../../../morfo/components/link-preview';
import { Soma } from '../../core/soma.svelte'; import { Soma } from '../../core/soma.svelte';
import type { SomaRuntimePart } from '../../runtime.svelte'; import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
// ── Root ───────────────────────────────────────────────────────────────────── // ── Root ─────────────────────────────────────────────────────────────────────
@ -38,6 +38,8 @@ interface LinkPreviewOpts
export class LinkPreviewProvider { export class LinkPreviewProvider {
readonly opts: LinkPreviewOpts; readonly opts: LinkPreviewOpts;
readonly runtimePart: SomaRuntimePart; readonly runtimePart: SomaRuntimePart;
readonly soma: Soma;
readonly runtime: SomaRuntime;
static readonly ctx = context<LinkPreviewProvider>('LinkPreview'); static readonly ctx = context<LinkPreviewProvider>('LinkPreview');
static get(): LinkPreviewProvider | undefined { static get(): LinkPreviewProvider | undefined {
return this.ctx.getOr(undefined) as LinkPreviewProvider | undefined; return this.ctx.getOr(undefined) as LinkPreviewProvider | undefined;
@ -63,14 +65,14 @@ export class LinkPreviewProvider {
private constructor(opts: LinkPreviewOpts) { private constructor(opts: LinkPreviewOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require() this.soma = Soma.require();
.runtime(linkPreviewMorfo, {}) this.runtime = this.soma.runtime(linkPreviewMorfo, {});
.part('provider', { this.runtimePart = this.runtime.part('provider', {
id: opts.id, id: opts.id,
ref: opts.ref, ref: opts.ref,
owner: this, owner: this,
context: LinkPreviewProvider.ctx context: LinkPreviewProvider.ctx
}); });
this.floatingProvider = FloatingProvider.create(); this.floatingProvider = FloatingProvider.create();
@ -164,17 +166,15 @@ export class LinkPreviewTriggerProvider {
private constructor(opts: LinkPreviewTriggerOpts) { private constructor(opts: LinkPreviewTriggerOpts) {
// A30: mirror trigger element to provider via `onRefChange`. // A30: mirror trigger element to provider via `onRefChange`.
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require()
.runtime(linkPreviewMorfo, {})
.part('trigger', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.provider.triggerRef.current = el;
}
});
this.provider = LinkPreviewProvider.require(); this.provider = LinkPreviewProvider.require();
this.runtimePart = this.provider.runtime.part('trigger', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.provider.triggerRef.current = el;
}
});
this.provider.triggerId.current = opts.id.current; this.provider.triggerId.current = opts.id.current;
FloatingAnchor.create({ FloatingAnchor.create({
@ -245,17 +245,15 @@ export class LinkPreviewContentProvider {
private constructor(opts: LinkPreviewContentOpts) { private constructor(opts: LinkPreviewContentOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require()
.runtime(linkPreviewMorfo, {})
.part('content', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.provider.setContentRef(el);
}
});
this.provider = LinkPreviewProvider.require(); this.provider = LinkPreviewProvider.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; this.provider.contentId.current = opts.id.current;
this.floating = FloatingContent.create({ this.floating = FloatingContent.create({
@ -344,6 +342,7 @@ interface LinkPreviewArrowOpts extends WithRefOpts {}
export class LinkPreviewArrowProvider { export class LinkPreviewArrowProvider {
readonly opts: LinkPreviewArrowOpts; readonly opts: LinkPreviewArrowOpts;
readonly runtimePart: SomaRuntimePart; readonly runtimePart: SomaRuntimePart;
readonly provider: LinkPreviewProvider;
static create(opts: LinkPreviewArrowOpts) { static create(opts: LinkPreviewArrowOpts) {
return new LinkPreviewArrowProvider(opts); return new LinkPreviewArrowProvider(opts);
} }
@ -352,9 +351,12 @@ export class LinkPreviewArrowProvider {
private constructor(opts: LinkPreviewArrowOpts) { private constructor(opts: LinkPreviewArrowOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require() this.provider = LinkPreviewProvider.require();
.runtime(linkPreviewMorfo, {}) this.runtimePart = this.provider.runtime.part('arrow', {
.part('arrow', { id: opts.id, ref: opts.ref, owner: this }); id: opts.id,
ref: opts.ref,
owner: this
});
this.floatingArrow = FloatingArrow.create(opts); this.floatingArrow = FloatingArrow.create(opts);
} }

@ -7,7 +7,7 @@ import { SCROLL_AREA_LANGS } from './langs';
import { isBrowser } from '$adom'; import { isBrowser } from '$adom';
import { scrollAreaMorfo } from '../../../morfo/components/scroll-area'; import { scrollAreaMorfo } from '../../../morfo/components/scroll-area';
import type { SomaRuntimePart } from '../../runtime.svelte'; import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
export type ScrollAreaType = 'hover' | 'scroll' | 'auto' | 'always'; export type ScrollAreaType = 'hover' | 'scroll' | 'auto' | 'always';
@ -26,6 +26,8 @@ interface ScrollAreaOpts
export class ScrollAreaProvider { export class ScrollAreaProvider {
readonly opts: ScrollAreaOpts; readonly opts: ScrollAreaOpts;
readonly runtimePart: SomaRuntimePart; readonly runtimePart: SomaRuntimePart;
readonly soma: Soma;
readonly runtime: SomaRuntime;
static readonly ctx = context<ScrollAreaProvider>('ScrollArea'); static readonly ctx = context<ScrollAreaProvider>('ScrollArea');
static get(): ScrollAreaProvider | undefined { static get(): ScrollAreaProvider | undefined {
return this.ctx.getOr(undefined) as ScrollAreaProvider | undefined; return this.ctx.getOr(undefined) as ScrollAreaProvider | undefined;
@ -38,8 +40,6 @@ export class ScrollAreaProvider {
return new ScrollAreaProvider(opts); return new ScrollAreaProvider(opts);
} }
readonly soma = Soma.get();
// Viewport tracking // Viewport tracking
viewportRef = state<HTMLElement | null>(null); viewportRef = state<HTMLElement | null>(null);
contentWidth = $state(0); contentWidth = $state(0);
@ -53,14 +53,14 @@ export class ScrollAreaProvider {
private constructor(opts: ScrollAreaOpts) { private constructor(opts: ScrollAreaOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require() this.soma = Soma.require();
.runtime(scrollAreaMorfo, {}) this.runtime = this.soma.runtime(scrollAreaMorfo, {});
.part('provider', { this.runtimePart = this.runtime.part('provider', {
id: opts.id, id: opts.id,
ref: opts.ref, ref: opts.ref,
owner: this, owner: this,
context: ScrollAreaProvider.ctx context: ScrollAreaProvider.ctx
}); });
// Cleanup resize observer on unmount // Cleanup resize observer on unmount
$effect(() => { $effect(() => {
@ -169,17 +169,15 @@ export class ScrollAreaViewportProvider {
private constructor(opts: ScrollAreaViewportOpts) { private constructor(opts: ScrollAreaViewportOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require()
.runtime(scrollAreaMorfo, {})
.part('viewport', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.provider.setupViewport(el);
}
});
this.provider = ScrollAreaProvider.require(); this.provider = ScrollAreaProvider.require();
this.runtimePart = this.provider.runtime.part('viewport', {
id: opts.id,
ref: opts.ref,
owner: this,
onRefChange: (el) => {
this.provider.setupViewport(el);
}
});
} }
readonly onscroll = (e: Event) => { readonly onscroll = (e: Event) => {
@ -241,15 +239,13 @@ export class ScrollAreaScrollbarProvider {
private constructor(opts: ScrollAreaScrollbarOpts) { private constructor(opts: ScrollAreaScrollbarOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require()
.runtime(scrollAreaMorfo, {})
.part('scrollbar', {
id: opts.id,
ref: opts.ref,
owner: this,
context: ScrollAreaScrollbarProvider.ctx
});
this.provider = ScrollAreaProvider.require(); this.provider = ScrollAreaProvider.require();
this.runtimePart = this.provider.runtime.part('scrollbar', {
id: opts.id,
ref: opts.ref,
owner: this,
context: ScrollAreaScrollbarProvider.ctx
});
// Skip initial-mount flash — defer mounted flag to next frame // Skip initial-mount flash — defer mounted flag to next frame
requestAnimationFrame(() => { requestAnimationFrame(() => {
@ -387,8 +383,8 @@ export class ScrollAreaScrollbarProvider {
'aria-valuemax': 100, 'aria-valuemax': 100,
'aria-orientation': this.opts.orientation.current, 'aria-orientation': this.opts.orientation.current,
'aria-label': this.isVertical 'aria-label': this.isVertical
? this.provider.soma?.langs.ts(SCROLL_AREA_LANGS.SCROLLBAR_VERTICAL) ? this.provider.soma.langs.ts(SCROLL_AREA_LANGS.SCROLLBAR_VERTICAL)
: this.provider.soma?.langs.ts(SCROLL_AREA_LANGS.SCROLLBAR_HORIZONTAL), : this.provider.soma.langs.ts(SCROLL_AREA_LANGS.SCROLLBAR_HORIZONTAL),
tabindex: -1, tabindex: -1,
'data-state': this.shouldShow ? 'visible' : 'hidden', 'data-state': this.shouldShow ? 'visible' : 'hidden',
'data-orientation': this.opts.orientation.current, 'data-orientation': this.opts.orientation.current,
@ -424,11 +420,13 @@ export class ScrollAreaThumbProvider {
private constructor(opts: ScrollAreaThumbOpts) { private constructor(opts: ScrollAreaThumbOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require()
.runtime(scrollAreaMorfo, {})
.part('thumb', { id: opts.id, ref: opts.ref, owner: this });
this.scrollbar = ScrollAreaScrollbarProvider.require(); this.scrollbar = ScrollAreaScrollbarProvider.require();
this.provider = this.scrollbar.provider; this.provider = this.scrollbar.provider;
this.runtimePart = this.provider.runtime.part('thumb', {
id: opts.id,
ref: opts.ref,
owner: this
});
} }
private get isVertical(): boolean { private get isVertical(): boolean {
@ -561,10 +559,12 @@ export class ScrollAreaCornerProvider {
private constructor(opts: ScrollAreaCornerOpts) { private constructor(opts: ScrollAreaCornerOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require()
.runtime(scrollAreaMorfo, {})
.part('corner', { id: opts.id, ref: opts.ref, owner: this });
this.provider = ScrollAreaProvider.require(); this.provider = ScrollAreaProvider.require();
this.runtimePart = this.provider.runtime.part('corner', {
id: opts.id,
ref: opts.ref,
owner: this
});
} }
readonly shouldShow = $derived.by(() => this.provider.hasOverflowX && this.provider.hasOverflowY); readonly shouldShow = $derived.by(() => this.provider.hasOverflowX && this.provider.hasOverflowY);

@ -30,7 +30,7 @@ import {
import { tooltipMorfo } from '../../../morfo/components/tooltip'; import { tooltipMorfo } from '../../../morfo/components/tooltip';
import { Soma } from '../../core/soma.svelte'; import { Soma } from '../../core/soma.svelte';
import type { SomaRuntimePart } from '../../runtime.svelte'; import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
export type TooltipState = 'closed' | 'delayed-open' | 'instant-open'; export type TooltipState = 'closed' | 'delayed-open' | 'instant-open';
@ -93,6 +93,8 @@ interface TooltipOpts
export class TooltipProvider { export class TooltipProvider {
readonly opts: TooltipOpts; readonly opts: TooltipOpts;
readonly runtimePart: SomaRuntimePart; readonly runtimePart: SomaRuntimePart;
readonly soma: Soma;
readonly runtime: SomaRuntime;
static readonly ctx = context<TooltipProvider>('Tooltip'); static readonly ctx = context<TooltipProvider>('Tooltip');
static get(): TooltipProvider | undefined { static get(): TooltipProvider | undefined {
return this.ctx.getOr(undefined) as TooltipProvider | undefined; return this.ctx.getOr(undefined) as TooltipProvider | undefined;
@ -137,9 +139,14 @@ export class TooltipProvider {
private constructor(opts: TooltipOpts) { private constructor(opts: TooltipOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require() this.soma = Soma.require();
.runtime(tooltipMorfo, {}) this.runtime = this.soma.runtime(tooltipMorfo, {});
.part('provider', { id: opts.id, ref: opts.ref, owner: this, context: TooltipProvider.ctx }); this.runtimePart = this.runtime.part('provider', {
id: opts.id,
ref: opts.ref,
owner: this,
context: TooltipProvider.ctx
});
this.group = TooltipGroupProvider.get(); this.group = TooltipGroupProvider.get();
this.floatingProvider = FloatingProvider.create(); this.floatingProvider = FloatingProvider.create();
@ -257,27 +264,22 @@ export class TooltipTriggerProvider {
// A30: mirror trigger element to provider via `onRefChange`. // A30: mirror trigger element to provider via `onRefChange`.
this.opts = opts; this.opts = opts;
this.provider = TooltipProvider.require(); this.provider = TooltipProvider.require();
this.runtimePart = Soma.require() this.runtimePart = this.provider.runtime.part('trigger', {
.runtime(tooltipMorfo, { id: opts.id,
states: { ref: opts.ref,
'instant-open': () => this.provider.tooltipState states: {
}, 'instant-open': () => this.provider.tooltipState
parts: { },
content: () => parts: {
this.provider.opts.open.current content: () =>
? this.provider.contentId.current || undefined this.provider.opts.open.current ? this.provider.contentId.current || undefined : undefined
: undefined },
} owner: this,
}) onRefChange: (el) => {
.part('trigger', { this.provider.triggerRef.current = el;
id: opts.id, },
ref: opts.ref, syncAttrs: true
owner: this, });
onRefChange: (el) => {
this.provider.triggerRef.current = el;
},
syncAttrs: true
});
this.provider.triggerId.current = opts.id.current; this.provider.triggerId.current = opts.id.current;
FloatingAnchor.create({ FloatingAnchor.create({
@ -353,24 +355,21 @@ export class TooltipContentProvider {
private constructor(opts: TooltipContentOpts) { private constructor(opts: TooltipContentOpts) {
this.opts = opts; this.opts = opts;
this.provider = TooltipProvider.require(); this.provider = TooltipProvider.require();
this.runtimePart = Soma.require() this.runtimePart = this.provider.runtime.part('content', {
.runtime(tooltipMorfo, { id: opts.id,
states: { ref: opts.ref,
'instant-open': () => this.provider.tooltipState states: {
}, 'instant-open': () => this.provider.tooltipState
props: { },
ariaLabel: () => this.opts.ariaLabel.current props: {
} ariaLabel: () => this.opts.ariaLabel.current
}) },
.part('content', { owner: this,
id: opts.id, onRefChange: (el) => {
ref: opts.ref, this.provider.setContentRef(el);
owner: this, },
onRefChange: (el) => { syncAttrs: true
this.provider.setContentRef(el); });
},
syncAttrs: true
});
this.provider.contentId.current = opts.id.current; this.provider.contentId.current = opts.id.current;
// Floating // Floating
@ -453,6 +452,7 @@ interface TooltipArrowOpts extends WithRefOpts {}
export class TooltipArrowProvider { export class TooltipArrowProvider {
readonly opts: TooltipArrowOpts; readonly opts: TooltipArrowOpts;
readonly runtimePart: SomaRuntimePart; readonly runtimePart: SomaRuntimePart;
readonly provider: TooltipProvider;
static create(opts: TooltipArrowOpts) { static create(opts: TooltipArrowOpts) {
return new TooltipArrowProvider(opts); return new TooltipArrowProvider(opts);
} }
@ -461,9 +461,12 @@ export class TooltipArrowProvider {
private constructor(opts: TooltipArrowOpts) { private constructor(opts: TooltipArrowOpts) {
this.opts = opts; this.opts = opts;
this.runtimePart = Soma.require() this.provider = TooltipProvider.require();
.runtime(tooltipMorfo, {}) this.runtimePart = this.provider.runtime.part('arrow', {
.part('arrow', { id: opts.id, ref: opts.ref, owner: this }); id: opts.id,
ref: opts.ref,
owner: this
});
this.floatingArrow = FloatingArrow.create(opts); this.floatingArrow = FloatingArrow.create(opts);
} }

Loading…
Cancel
Save

Powered by TurnKey Linux.