Spaces:
Running
Running
Download src/components/OutputView.tsx from mrfakename/flow: direct link, hf CLI and curl.
- Browser
- Download file 4.21 kB
-
https://huggingface.co/spaces/mrfakename/flow/resolve/main/src/components/OutputView.tsx
- Command line
-
hf download hf://spaces/mrfakename/flow/src/components/OutputView.tsx
-
curl -L -o OutputView.tsx https://huggingface.co/spaces/mrfakename/flow/resolve/main/src/components/OutputView.tsx
4.21 kB
| import { ArrowSquareOutIcon, FileIcon, HourglassIcon } from "@phosphor-icons/react"; | |
| import type { DataType, FileRef, OutputValue } from "../lib/types"; | |
| const isRef = (v: unknown): v is FileRef => !!v && typeof v === "object" && typeof (v as FileRef).url === "string"; | |
| const isImageUrl = (u: string) => /\.(png|jpe?g|webp|gif|avif|bmp|svg)(\?|$)/i.test(u); | |
| const isAudioUrl = (u: string) => /\.(mp3|wav|ogg|flac|m4a|aac|opus)(\?|$)/i.test(u); | |
| const isVideoUrl = (u: string) => /\.(mp4|webm|mov|mkv)(\?|$)/i.test(u); | |
| const kindOf = (ref: FileRef, hint: DataType): "image" | "audio" | "video" | "file" => { | |
| const m = ref.mime ?? ""; | |
| if (m.startsWith("image/") || isImageUrl(ref.url)) return "image"; | |
| if (m.startsWith("audio/") || isAudioUrl(ref.url)) return "audio"; | |
| if (m.startsWith("video/") || isVideoUrl(ref.url)) return "video"; | |
| if (hint === "image" || hint === "audio" || hint === "video") return hint; | |
| return "file"; | |
| }; | |
| function FileView({ file, hint }: { file: FileRef; hint: DataType }) { | |
| const kind = kindOf(file, hint); | |
| const open = ( | |
| <a className="node-output__open nodrag" href={file.url} target="_blank" rel="noreferrer" title="Open in a new tab" onClick={(e) => e.stopPropagation()}> | |
| <ArrowSquareOutIcon size={12} weight="bold" /> | |
| </a> | |
| ); | |
| switch (kind) { | |
| case "image": | |
| return ( | |
| <> | |
| <img src={file.url} alt={file.name ?? ""} draggable={false} /> | |
| {open} | |
| </> | |
| ); | |
| case "audio": | |
| return ( | |
| <> | |
| <audio src={file.url} controls className="nodrag" preload="metadata" /> | |
| {open} | |
| </> | |
| ); | |
| case "video": | |
| return ( | |
| <> | |
| <video src={file.url} controls className="nodrag" preload="metadata" /> | |
| {open} | |
| </> | |
| ); | |
| default: | |
| return ( | |
| <a className="node-output__file nodrag" href={file.url} target="_blank" rel="noreferrer"> | |
| <FileIcon size={13} /> | |
| <span className="truncate">{file.name ?? file.url.split("/").pop()}</span> | |
| </a> | |
| ); | |
| } | |
| } | |
| /** Renders one output port's value. */ | |
| export function OutputView({ value, type, pending }: { value: OutputValue | undefined; type: DataType; pending?: boolean }) { | |
| if (value === undefined || value === null || value === "") { | |
| return ( | |
| <div className="node-output"> | |
| <div className="node-output__empty"> | |
| {pending ? <HourglassIcon size={12} /> : null} | |
| <span>{pending ? "Waiting…" : "No output yet"}</span> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| if (isRef(value)) { | |
| return ( | |
| <div className="node-output"> | |
| <FileView file={value} hint={type} /> | |
| </div> | |
| ); | |
| } | |
| if (Array.isArray(value) && value.length && value.every(isRef)) { | |
| const refs = value as FileRef[]; | |
| if (refs.length === 1 || (type === "image" && refs.every((r) => kindOf(r, type) === "image"))) | |
| return ( | |
| <div className="node-output"> | |
| <FileView file={refs[refs.length - 1]} hint={type} /> | |
| </div> | |
| ); | |
| return ( | |
| <div className="node-output"> | |
| <div className="node-output__grid"> | |
| {refs.slice(0, 9).map((r, i) => | |
| kindOf(r, "image") === "image" ? ( | |
| <a key={i} href={r.url} target="_blank" rel="noreferrer" className="nodrag"> | |
| <img src={r.url} alt="" draggable={false} /> | |
| </a> | |
| ) : ( | |
| <FileView key={i} file={r} hint="file" /> | |
| ), | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } | |
| const text = typeof value === "string" ? value : typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value, null, 1); | |
| return ( | |
| <div className="node-output"> | |
| <pre className="node-output__text nodrag nowheel">{text.length > 2000 ? `${text.slice(0, 2000)}…` : text}</pre> | |
| </div> | |
| ); | |
| } | |
| /** First image URL in a value, for thumbnails. */ | |
| export const thumbOf = (value: OutputValue | undefined): string | null => { | |
| if (isRef(value)) return kindOf(value, "image") === "image" ? value.url : null; | |
| if (Array.isArray(value)) for (const v of value) if (isRef(v) && kindOf(v, "image") === "image") return v.url; | |
| return null; | |
| }; | |