import { consume } from "@lit/context"; import { css, html, type PropertyValues } from "lit"; import { property } from "lit/decorators.js"; import type { RuntimeClient } from "@commonfabric/runtime-client"; import { BaseElement } from "../../core/base-element.ts"; import { runtimeContext } from "../../runtime-context.ts"; import { type BlobReference, BlobUrlResolver } from "../../utils/blob-url.ts"; /** * CFBlobLink - A link that downloads a blob from a space's blob store. * * `blob` names the blob, by its space's DID and its id there, as a FabriFile * entry holds them. The component asks the runtime for the URL that space's * host serves the blob at for saving, and renders its content as a link to it, * which saves the file under `name` from any origin. A pattern offers a stored * file this way without forming a URL itself. Until the URL arrives, and for a * reference that names no blob, the content is shown as plain text. * * @element cf-blob-link * * @property {object} blob - The blob, as `{ space, id }` * @attr {string} name - The name to save the file under * @slot - The link's content */ export class CFBlobLink extends BaseElement { static override styles = [ BaseElement.baseStyles, css` :host { display: inline; } a { color: inherit; } `, ]; /** The blob to link to, by its space and its id. */ @property({ attribute: false }) accessor blob: BlobReference | undefined = undefined; /** The name the file is saved under. */ @property({ type: String }) accessor name = ""; /** The runtime that resolves `blob` to a URL. */ @consume({ context: runtimeContext, subscribe: true }) @property({ attribute: false }) accessor runtime: RuntimeClient | undefined = undefined; #url = new BlobUrlResolver(this, { download: true }); override willUpdate(changedProperties: PropertyValues) { super.willUpdate(changedProperties); if (changedProperties.has("blob") || changedProperties.has("runtime")) { this.#url.resolve(this.runtime, this.blob); } } override render() { const url = this.#url.url; return url === null ? html`` : html` `; } } declare global { interface HTMLElementTagNameMap { "cf-blob-link": CFBlobLink; } }