///
///
import { hydrate, mount } from 'svelte';
import type { Component } from 'svelte';
import { parse as devalueParse } from 'devalue';
import { isDev, logger } from 'mochi-framework';
import './IslandFailure';
import { islandFailureStub } from './islandFailureStub';
import { observeVisible } from './sharedVisibilityObserver';
import { isLoadedCss, markLoadedCss } from './sharedCssTracker';
const componentRegistry: Record = {};
export function registerComponent(name: string, component: Component) {
componentRegistry[name] = component;
}
class HydratableIsland extends HTMLElement {
_hydrated = false;
connectedCallback() {
const name = this.getAttribute('component-name');
const hydrateOn = this.getAttribute('hydrate-on');
logger.log('connectedCallback', {
name,
hydrateOn,
attributes: [...this.attributes].map((a) => a.name + '=' + a.value),
});
if (this._hydrated) {
return;
}
if (hydrateOn === 'visible') {
const optionsRaw = this.getAttribute('hydrate-options');
const options = optionsRaw ? JSON.parse(optionsRaw) : {};
// Observe firstElementChild because display:contents gives this element no layout box
const target = this.firstElementChild || this;
observeVisible(target, options.rootMargin || '0px', () => this._doHydrate());
} else {
// Eager islands: load component JS immediately, then hydrate
this._doHydrate();
}
}
async _doHydrate() {
if (this._hydrated) {
return;
}
this._hydrated = true;
const name = this.getAttribute('component-name');
try {
await this._doHydrateInner(name);
} catch (err) {
// Defensive belt — `transformError` on `hydrate()` covers errors raised
// by the boundary; this catches synchronous throws from the bundle import,
// CSS load, or `hydrate()` itself before the boundary takes effect.
const e = err instanceof Error ? err : new Error(String(err));
logger.error(`Island "${name}" failed to hydrate:`, e);
this.innerHTML = islandFailureStub(name ?? '', isDev ? e.message : undefined);
}
}
async _doHydrateInner(name: string | null) {
if (!name) {
return;
}
// Page islands carry a `props-ref` pointing at a `