Skip to content
fayeuiStatic / 0.1.0
LLMs
Advanced / Static edition

Atomic theme asset loading

Prepare a trusted stylesheet, then commit identity and appearance together.

Loading contract

createThemeAssetManager belongs to a DOM theme scope. It stages trusted stylesheets, validates allowed origins, supports integrity and a timeout, and keeps the last valid theme while another is loading.

A newer load cancels and supersedes an older load. Failed preparation or activation does not discard the current asset. Disposal aborts pending work and restores the previous identity only when the manager still owns that attribute.

import { createThemeAssetManager } from '@fayegram-ai/faye-ui/theme/assets';
const manager = createThemeAssetManager(document.documentElement, {
  allowedOrigins: ['https://assets.your-domain.example'],
  onCommit: id => updateApplicationThemeId(id),
});
await manager.load({ id: 'brand-a', href: '/themes/brand-a.css' });
// During application teardown:
manager.dispose();

The callback is application code; it must synchronize the provider's identity. Do not let another provider effect overwrite a manager-owned theme. Stylesheets must use the expected theme scope selectors. Origin validation is not a CSS sandbox.

Pure and browser evidence

The state-machine tests cover stale completions, failure, cancellation and cleanup. Browser tests use controlled link load/error events to inspect DOM ownership; they do not prove an external CDN or integrity policy is operational.

Cleanup diagnostics

Successful activation commits before the previous asset is disposed. A disposal error cannot retroactively turn that committed switch into a failed load. getCleanupErrors() exposes cleanup failures separately; the browser manager removes its own link nodes without third-party cleanup code. A rejected activation still reports the original activation error, not a secondary disposal error.

The target must carry the effective data-faye-ui-theme, data-faye-ui-scheme, and data-faye-ui-density attributes used by compiled themes. FayeUIProvider and ThemeScope supply them.

Synchronous activation boundary

Activation and onCommit are synchronous. Reentrant load or disposal during activation is rejected before it can corrupt ownership or supersede the committing asset. Schedule another transition after the commit. Cleanup errors from a previous asset are diagnostic and do not reverse a successfully committed theme.

Controlled DOM link events in the offline browser suite are not evidence of real network delivery, integrity enforcement, Next streaming or hydration behavior. Those remain separate integration gates.

Origin, integrity and style-root policy

Relative URLs use the document's base URI for resolution. Permission comes from the document URL's HTTP(S) origin plus explicit allowedOrigins, not from an external base element. Opaque-origin documents must declare allowedOrigins. Entries must be origins, not URL paths or credential-bearing URLs; case and default ports are normalized.

The manager installs a link in the target's shadow root when applicable, rather than injecting a shadow theme into the document head. Moving to another document or style root during preparation rejects activation and removes the staged link. Start a new load after moving the scope. Static component/reset CSS still needs independent installation in the shadow root; this loader does not transport arbitrary application styles or prove initially open portal behavior.

When integrity is supplied, Faye UI accepts a bounded list of canonical padded-base64 sha256, sha384 or sha512 digests. Unknown algorithms, truncated digests and metadata options are rejected rather than relying on the browser to ignore them. This is a deliberately restricted authoring policy, not complete SRI grammar support. The browser still must fetch and verify the actual bytes; a syntactically valid hash is not proof of delivery or authenticity. Cross-origin assets use anonymous CORS when integrity is set.

A rejected URL or malformed metadata does not cancel an already valid pending request. Caller-owned request objects are snapshotted. Cancellation settles the returned promise even when a custom preparer ignores AbortSignal; any resource it returns later is disposed without activation. Cancellation cannot forcibly stop work in a noncooperating preparer.

Reentrant loads or disposal during synchronous request handoff, activation or resource cleanup are rejected. Schedule the next transition after the current operation. A cleanup failure remains diagnostic instead of silently disposing the newly committed theme.