diff options
Diffstat (limited to 'source/library/components/ResultViewer.svelte')
| -rw-r--r-- | source/library/components/ResultViewer.svelte | 97 |
1 files changed, 67 insertions, 30 deletions
diff --git a/source/library/components/ResultViewer.svelte b/source/library/components/ResultViewer.svelte index d277ec8..270965b 100644 --- a/source/library/components/ResultViewer.svelte +++ b/source/library/components/ResultViewer.svelte @@ -1,7 +1,10 @@ <script lang="ts"> - import Editor from "./Editor.svelte"; + /*** IMPORT ------------------------------------------- ***/ import type { Extension } from "@codemirror/state"; import type { Snippet } from "svelte"; + + /*** UTILITY ------------------------------------------ ***/ + import Editor from "./Editor.svelte"; import type { TabTiming } from "../state/session.svelte.ts"; type Props = { @@ -20,18 +23,6 @@ value }: Props = $props(); - function median(values: number[]): number { - if (values.length === 0) - return 0; - - const sorted = [...values].sort((a, b) => a - b); - const mid = Math.floor(sorted.length / 2); - - return sorted.length % 2 === 0 ? - (sorted[mid - 1] + sorted[mid]) / 2 : - sorted[mid]; - } - let metadata = $derived.by(() => { if (!timing) return null; @@ -39,55 +30,101 @@ if (streamIntervals.length > 0) { const medianMs = Math.round(median(streamIntervals)); const messages = streamIntervals.length + 1; - return `→ ${messages} messages · median ${medianMs}ms`; + return `${messages} messages · median ${medianMs}ms`; } const totalMs = Math.round(timing.endMs - timing.startMs); const firstByteMs = Math.round(timing.firstByteMs - timing.startMs); - return `→ ${totalMs}ms · first byte ${firstByteMs}ms`; + return `${totalMs}ms · first byte ${firstByteMs}ms`; }); + /*** HELPER ------------------------------------------- ***/ + function median(values: number[]): number { + if (values.length === 0) + return 0; + + const sorted = [...values].sort((a, b) => a - b); + const mid = Math.floor(sorted.length / 2); + + return sorted.length % 2 === 0 ? + (sorted[mid - 1] + sorted[mid]) / 2 : + sorted[mid]; + } + function noop(_v: string) {} </script> <style lang="scss"> .result { - display: grid; - grid-template-rows: auto 1fr auto auto; + display: flex; + flex-direction: column; height: 100%; min-height: 0; + position: relative; } - .label { - background: var(--graphiql-panel, #252526); + .label, + .metadata, + .footer { font-size: 0.75rem; - letter-spacing: 0.05em; padding: 0.25rem 0.75rem; + } + + .label, + .metadata { + background-color: var(--uchu-gray-2); + color: var(--uchu-yin-7); + } + + .label { + top: 1rem; right: 1rem; + + border: 1px solid var(--uchu-gray-3); + font-weight: 600; + letter-spacing: 0.05rem; + pointer-events: none; + position: absolute; text-transform: uppercase; + z-index: 1; + } + + .metadata, + .footer { + position: relative; } .metadata { - background: var(--graphiql-panel, #252526); - border-top: 1px solid var(--graphiql-border, #333); - color: var(--graphiql-muted, #858585); - font-size: 0.75rem; - padding: 0.25rem 0.75rem; + align-items: center; + display: flex; + flex-direction: row; + + svg { + width: 1rem; height: 1rem; + margin-right: 0.25rem; + } } .footer { - background: var(--graphiql-panel, #252526); - border-top: 1px solid var(--graphiql-border, #333); - font-size: 0.75rem; - padding: 0.25rem 0.75rem; + background-color: var(--uchu-gray-3); + border-top: 1px solid var(--uchu-gray-4); } </style> <div class="result"> <div class="label">Response</div> + <Editor language="json" onChange={noop} readOnly {theme} {value}/> + {#if metadata} - <div class="metadata">{metadata}</div> + <div class="metadata"> + <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M14 5.75L20.25 12L14 18.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"/> + <path d="M19.5 12H3.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"/> + </svg> + {@html metadata} + </div> {/if} + {#if footer} <div class="footer">{@render footer({ result: value })}</div> {/if} |