UNPKG

@sanity/vision

Version:

Sanity plugin for running/debugging GROQ-queries against Sanity datasets

1,185 lines (1,148 loc) 69.8 kB
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime"; import { c } from "react-compiler-runtime"; import { useTranslation, Translate, usePerspective, useDataset, useClient } from "sanity"; import { useState, useEffect, forwardRef, useRef, useImperativeHandle, Fragment, useMemo, useCallback, createElement, Component } from "react"; import { Spinner, rem, useTheme, Flex, Box, Card, Label, Text, Tooltip, Hotkeys, Button, useClickOutsideEvent, Popover, Inline, Badge, Stack, TextInput, Grid, Select, Code, useToast, Container, Heading } from "@sanity/ui"; import { SplitPane } from "@rexxars/react-split-pane"; import { isHotkey } from "is-hotkey-esm"; import { useEffectEvent } from "use-effect-event"; import CodeMirror, { EditorSelection } from "@uiw/react-codemirror"; import { closeBrackets } from "@codemirror/autocomplete"; import { history, defaultKeymap, historyKeymap } from "@codemirror/commands"; import { javascriptLanguage } from "@codemirror/lang-javascript"; import { indentOnInput, bracketMatching, syntaxHighlighting, defaultHighlightStyle, HighlightStyle } from "@codemirror/language"; import { highlightSelectionMatches } from "@codemirror/search"; import { lineNumbers, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, drawSelection, keymap, EditorView } from "@codemirror/view"; import { tags } from "@lezer/highlight"; import { hues } from "@sanity/color"; import { styled, css } from "styled-components"; import { visionLocaleNamespace } from "./index.mjs"; import { ErrorOutlineIcon, StopIcon, PlayIcon, HelpCircleIcon, CopyIcon, LinkIcon, DocumentSheetIcon } from "@sanity/icons"; import debounce from "lodash/debounce.js"; import JSON5 from "json5"; import { json2csv } from "json-2-csv"; import { JsonInspector } from "@rexxars/react-json-inspector"; import LRU from "quick-lru"; import { IntentLink } from "sanity/router"; const API_VERSIONS = ["v1", "vX", "v2021-03-25", "v2021-10-21", "v2022-03-07", "v2025-02-19", `v${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`], [DEFAULT_API_VERSION] = API_VERSIONS.slice(-1); function DelayedSpinner(props) { const $ = c(5), [show, setShow] = useState(!1); let t0, t1; $[0] !== props.delay ? (t0 = () => { const timer = setTimeout(() => setShow(!0), props.delay || 500); return () => clearTimeout(timer); }, t1 = [props.delay], $[0] = props.delay, $[1] = t0, $[2] = t1) : (t0 = $[1], t1 = $[2]), useEffect(t0, t1); let t2; return $[3] !== show ? (t2 = show ? /* @__PURE__ */ jsx(Spinner, { muted: !0, size: 4 }) : null, $[3] = show, $[4] = t2) : t2 = $[4], t2; } const codemirrorExtensions = [[javascriptLanguage], lineNumbers(), highlightActiveLine(), highlightActiveLineGutter(), highlightSelectionMatches(), highlightSpecialChars(), indentOnInput(), bracketMatching(), closeBrackets(), history(), drawSelection(), syntaxHighlighting(defaultHighlightStyle, { fallback: !0 }), keymap.of([ // Override the default keymap for Mod-Enter to not insert a new line, we have a custom event handler for executing queries { key: "Mod-Enter", run: () => !0 }, // Add the default keymap and history keymap defaultKeymap, historyKeymap ].flat().filter(Boolean))]; function useCodemirrorTheme(theme) { const $ = c(7); let t0, t1; $[0] !== theme ? (t1 = createTheme(theme), $[0] = theme, $[1] = t1) : t1 = $[1], t0 = t1; const cmTheme = t0; let t2, t3; $[2] !== theme ? (t3 = syntaxHighlighting(createHighlight(theme)), $[2] = theme, $[3] = t3) : t3 = $[3], t2 = t3; const cmHighlight = t2; let t4; return $[4] !== cmHighlight || $[5] !== cmTheme ? (t4 = [cmTheme, cmHighlight], $[4] = cmHighlight, $[5] = cmTheme, $[6] = t4) : t4 = $[6], t4; } function createTheme(theme) { const { color, fonts } = theme.sanity, card = color.card.enabled, cursor = hues.blue[color.dark ? 400 : 500].hex, selection = hues.gray[theme.sanity.color.dark ? 900 : 100].hex; return EditorView.theme({ "&": { color: card.fg, backgroundColor: card.bg }, ".cm-content": { caretColor: cursor }, ".cm-editor": { fontFamily: fonts.code.family, fontSize: rem(fonts.code.sizes[1].fontSize), lineHeight: "inherit" }, ".cm-cursor, .cm-dropCursor": { borderLeftColor: cursor }, "&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection": { backgroundColor: selection }, ".cm-panels": { backgroundColor: card.bg, color: card.fg }, ".cm-panels.cm-panels-top": { borderBottom: `2px solid ${card.border}` }, ".cm-panels.cm-panels-bottom": { borderTop: `2px solid ${card.border}` } }, { dark: color.dark }); } function createHighlight(theme) { const c2 = theme.sanity.color.base, s = theme.sanity.color.syntax; return HighlightStyle.define([{ tag: tags.keyword, color: s.keyword }, { tag: [tags.propertyName, tags.name, tags.deleted, tags.character, tags.macroName], color: s.property }, { tag: [tags.function(tags.variableName), tags.labelName], color: s.function }, { tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: s.variable }, { tag: [tags.definition(tags.name), tags.separator], color: s.constant }, { tag: [tags.typeName, tags.className, tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace], color: s.number }, { tag: [tags.operator, tags.operatorKeyword, tags.url, tags.escape, tags.regexp, tags.link, tags.special(tags.string)], color: s.operator }, { tag: [tags.meta, tags.comment], color: s.comment }, { tag: tags.strong, fontWeight: "bold" }, { tag: tags.emphasis, fontStyle: "italic" }, { tag: tags.strikethrough, textDecoration: "line-through" }, { tag: tags.heading, fontWeight: "bold", color: s.property }, { tag: [tags.atom, tags.bool, tags.special(tags.variableName)], color: s.boolean }, { tag: [tags.processingInstruction, tags.string, tags.inserted], color: s.string }, { tag: tags.invalid, color: c2.fg }]); } const EditorRoot = styled.div` width: 100%; box-sizing: border-box; height: 100%; overflow: hidden; overflow: clip; position: relative; display: flex; & .cm-theme { width: 100%; } & .cm-editor { height: 100%; font-size: 16px; line-height: 21px; } & .cm-line { padding-left: ${({ theme }) => rem(theme.sanity.space[3])}; } & .cm-content { border-right-width: ${({ theme }) => rem(theme.sanity.space[4])} !important; padding-top: ${({ theme }) => rem(theme.sanity.space[5])}; } `, VisionCodeMirror = forwardRef((props, ref) => { const $ = c(7), [initialValue] = useState(props.initialValue), sanityTheme = useTheme(), theme = useCodemirrorTheme(sanityTheme), codeMirrorRef = useRef(null); let t0; $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = (newContent) => { const editorView = codeMirrorRef.current?.view; if (!editorView) return; const currentDoc = editorView.state.doc.toString(); newContent !== currentDoc && editorView.dispatch({ changes: { from: 0, to: currentDoc.length, insert: newContent }, selection: EditorSelection.cursor(newContent.length) }); }, $[0] = t0) : t0 = $[0]; const resetEditorContent = t0; let t1, t2; $[1] === Symbol.for("react.memo_cache_sentinel") ? (t1 = () => ({ resetEditorContent }), t2 = [resetEditorContent], $[1] = t1, $[2] = t2) : (t1 = $[1], t2 = $[2]), useImperativeHandle(ref, t1, t2); let t3; return $[3] !== initialValue || $[4] !== props.onChange || $[5] !== theme ? (t3 = /* @__PURE__ */ jsx(EditorRoot, { children: /* @__PURE__ */ jsx(CodeMirror, { ref: codeMirrorRef, basicSetup: !1, theme, extensions: codemirrorExtensions, value: initialValue, onChange: props.onChange }) }), $[3] = initialValue, $[4] = props.onChange, $[5] = theme, $[6] = t3) : t3 = $[6], t3; }); VisionCodeMirror.displayName = "VisionCodeMirror"; const SUPPORTED_PERSPECTIVES = ["pinnedRelease", "raw", "published", "drafts"], VIRTUAL_PERSPECTIVES = ["pinnedRelease"]; function isSupportedPerspective(p) { return SUPPORTED_PERSPECTIVES.includes(p); } function isVirtualPerspective(maybeVirtualPerspective) { return typeof maybeVirtualPerspective == "string" && VIRTUAL_PERSPECTIVES.includes(maybeVirtualPerspective); } function hasPinnedPerspective({ selectedPerspectiveName }) { return typeof selectedPerspectiveName < "u"; } function getActivePerspective({ visionPerspective, perspectiveStack }) { return visionPerspective !== "pinnedRelease" ? visionPerspective : perspectiveStack; } function encodeQueryString(query, params = {}, options = {}) { const searchParams = new URLSearchParams(); searchParams.set("query", query); for (const [key, value] of Object.entries(params)) searchParams.set(`$${key}`, JSON.stringify(value)); for (const [key, value] of Object.entries(options)) value && searchParams.set(key, `${value}`); return `?${searchParams}`; } function isPlainObject(obj) { return !!obj && typeof obj == "object" && Object.prototype.toString.call(obj) === "[object Object]"; } const hasLocalStorage = supportsLocalStorage(), keyPrefix = "sanityVision:"; function clearLocalStorage() { if (hasLocalStorage) for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); key?.startsWith(keyPrefix) && localStorage.removeItem(key); } } function getLocalStorage(namespace) { const storageKey = `${keyPrefix}${namespace}`; let loadedState = null; return { get, set, merge }; function get(key, defaultVal) { const state = ensureState(); return typeof state[key] > "u" ? defaultVal : state[key]; } function set(key, value) { const state = ensureState(); return state[key] = value, localStorage.setItem(storageKey, JSON.stringify(loadedState)), value; } function merge(props) { const state = { ...ensureState(), ...props }; return localStorage.setItem(storageKey, JSON.stringify(state)), state; } function ensureState() { return loadedState === null && (loadedState = loadState()), loadedState; } function loadState() { if (!hasLocalStorage) return {}; try { const stored = JSON.parse(localStorage.getItem(storageKey) || "{}"); return isPlainObject(stored) ? stored : {}; } catch { return {}; } } } function supportsLocalStorage() { const mod = "lsCheck"; try { return localStorage.setItem(mod, mod), localStorage.removeItem(mod), !0; } catch { return !1; } } function parseApiQueryString(qs) { const params = {}, options = {}; for (const [key, value] of qs.entries()) { if (key[0] === "$") { params[key.slice(1)] = JSON.parse(value); continue; } if (key === "perspective") { options[key] = value; continue; } } return { query: qs.get("query") || "", params, options }; } function prefixApiVersion(version) { return version[0] !== "v" && version !== "other" ? `v${version}` : version; } function validateApiVersion(apiVersion) { const parseableApiVersion = apiVersion.replace(/^v/, "").trim().toUpperCase(); return parseableApiVersion.length > 0 && (parseableApiVersion === "X" || parseableApiVersion === "1" || /^\d{4}-\d{2}-\d{2}$/.test(parseableApiVersion) && !isNaN(Date.parse(parseableApiVersion))); } function tryParseParams(val, t) { try { const parsed = val ? JSON5.parse(val) : {}; return typeof parsed == "object" && parsed && !Array.isArray(parsed) ? parsed : {}; } catch (err) { return err.message = `${t("params.error.params-invalid-json")}: ${err.message.replace("JSON5:", "")}`, err; } } const Root = styled(Flex)` .sidebarPanes .Pane { overflow-y: auto; overflow-x: hidden; } & .Resizer { background: var(--card-border-color); opacity: 1; z-index: 1; box-sizing: border-box; background-clip: padding-box; border: solid transparent; } & .Resizer:hover { border-color: var(--card-shadow-ambient-color); } & .Resizer.horizontal { height: 11px; margin: -5px 0; border-width: 5px 0; cursor: row-resize; width: 100%; z-index: 4; } & .Resizer.vertical { width: 11px; margin: 0 -5px; border-width: 0 5px; cursor: col-resize; z-index: 2; /* To prevent the resizer from being hidden behind CodeMirror scroll area */ } .Resizer.disabled { cursor: not-allowed; } .Resizer.disabled:hover { border-color: transparent; } `; Root.displayName = "Root"; const Header = styled(Card)` border-bottom: 1px solid var(--card-border-color); `, StyledLabel = styled(Label)` flex: 1; `, SplitpaneContainer = styled(Box)` position: relative; `, QueryCopyLink = styled.a` cursor: pointer; margin-right: auto; `, InputBackgroundContainer = styled(Box)` position: absolute; top: 1rem; left: 0; padding: 0; margin: 0; z-index: 10; right: 0; ${StyledLabel} { user-select: none; } `, InputBackgroundContainerLeft = styled(InputBackgroundContainer)` // This is so its aligned with the gutters of CodeMirror left: 33px; `, InputContainer = styled(Card)` width: 100%; height: 100%; position: relative; flex-direction: column; `, ResultOuterContainer = styled(Flex)` height: 100%; `, ResultInnerContainer = styled(Box)` position: relative; `, ResultContainer = styled(Card)` height: 100%; width: 100%; position: absolute; max-width: 100%; ${({ $isInvalid }) => $isInvalid && css` &:after { background-color: var(--card-bg-color); content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 100%; } `} `, Result = styled(Box)` position: relative; width: 100%; height: 100%; z-index: 20; `, ResultFooter = styled(Flex)` border-top: 1px solid var(--card-border-color); `, TimingsCard = styled(Card)` position: relative; `; styled(Box)` width: 100%; height: 100%; `; const TimingsTextContainer = styled(Flex)` height: 100%; min-height: ${({ theme }) => rem(theme.sanity.space[3] * 2 + theme.sanity.fonts.text.sizes[2].lineHeight - theme.sanity.fonts.text.sizes[2].ascenderHeight - theme.sanity.fonts.text.sizes[2].descenderHeight)}; `, DownloadsCard = styled(Card)` position: relative; `, SaveResultLabel = styled(Text)` transform: initial; &:before, &:after { content: none; } > span { display: flex !important; gap: ${({ theme }) => rem(theme.sanity.space[3])}; align-items: center; } `, ControlsContainer = styled(Box)` border-top: 1px solid var(--card-border-color); `, defaultValue = `{ }`; function ParamsEditor(props) { const $ = c(33), { onChange, paramsError, hasValidParams, editorRef } = props, { t } = useTranslation(visionLocaleNamespace); let t0; $[0] !== props.value || $[1] !== t ? (t0 = parseParams(props.value, t), $[0] = props.value, $[1] = t, $[2] = t0) : t0 = $[2]; const { raw: value, error, parsed, valid } = t0, [isValid, setValid] = useState(valid), [init, setInit] = useState(!1); let t1, t2; $[3] !== error || $[4] !== init || $[5] !== isValid || $[6] !== onChange || $[7] !== parsed || $[8] !== value ? (t1 = () => { init || (onChange({ parsed, raw: value, valid: isValid, error }), setInit(!0)); }, t2 = [error, init, isValid, onChange, parsed, value], $[3] = error, $[4] = init, $[5] = isValid, $[6] = onChange, $[7] = parsed, $[8] = value, $[9] = t1, $[10] = t2) : (t1 = $[9], t2 = $[10]), useEffect(t1, t2); let t3; $[11] !== onChange || $[12] !== t ? (t3 = (newValue) => { const event = parseParams(newValue, t); setValid(event.valid), onChange(event); }, $[11] = onChange, $[12] = t, $[13] = t3) : t3 = $[13]; const handleChangeRaw = t3; let t4, t5; $[14] !== handleChangeRaw ? (t5 = debounce(handleChangeRaw, 333), $[14] = handleChangeRaw, $[15] = t5) : t5 = $[15], t4 = t5; const handleChange = t4, t6 = hasValidParams ? "default" : "critical"; let t7; $[16] !== t ? (t7 = t("params.label"), $[16] = t, $[17] = t7) : t7 = $[17]; let t8; $[18] !== t7 ? (t8 = /* @__PURE__ */ jsx(StyledLabel, { muted: !0, children: t7 }), $[18] = t7, $[19] = t8) : t8 = $[19]; let t9; $[20] !== paramsError ? (t9 = paramsError && /* @__PURE__ */ jsx(Tooltip, { animate: !0, placement: "top", portal: !0, content: /* @__PURE__ */ jsx(Text, { size: 1, children: paramsError }), children: /* @__PURE__ */ jsx(Box, { padding: 1, marginX: 2, children: /* @__PURE__ */ jsx(Text, { children: /* @__PURE__ */ jsx(ErrorOutlineIcon, {}) }) }) }), $[20] = paramsError, $[21] = t9) : t9 = $[21]; let t10; $[22] !== t8 || $[23] !== t9 ? (t10 = /* @__PURE__ */ jsx(InputBackgroundContainerLeft, { children: /* @__PURE__ */ jsxs(Flex, { children: [ t8, t9 ] }) }), $[22] = t8, $[23] = t9, $[24] = t10) : t10 = $[24]; const t11 = props.value || defaultValue; let t12; $[25] !== editorRef || $[26] !== handleChange || $[27] !== t11 ? (t12 = /* @__PURE__ */ jsx(VisionCodeMirror, { ref: editorRef, initialValue: t11, onChange: handleChange }), $[25] = editorRef, $[26] = handleChange, $[27] = t11, $[28] = t12) : t12 = $[28]; let t13; return $[29] !== t10 || $[30] !== t12 || $[31] !== t6 ? (t13 = /* @__PURE__ */ jsxs(Card, { flex: 1, tone: t6, "data-testid": "params-editor", children: [ t10, t12 ] }), $[29] = t10, $[30] = t12, $[31] = t6, $[32] = t13) : t13 = $[32], t13; } function parseParams(value, t) { const parsedParams = tryParseParams(value, t), params = parsedParams instanceof Error ? {} : parsedParams, validationError = parsedParams instanceof Error ? parsedParams.message : void 0; return { parsed: params, raw: value, valid: !validationError, error: validationError }; } function narrowBreakpoint() { return typeof window < "u" && window.innerWidth > 600; } function calculatePaneSizeOptions(height) { let rootHeight = height; return rootHeight || (rootHeight = typeof window < "u" && typeof document < "u" ? document.body.getBoundingClientRect().height - 60 : 0), { defaultSize: rootHeight / (narrowBreakpoint() ? 2 : 1), size: rootHeight > 550 ? void 0 : rootHeight * 0.4, allowResize: rootHeight > 550, minSize: Math.min(170, Math.max(170, rootHeight / 2)), maxSize: rootHeight > 650 ? rootHeight * 0.7 : rootHeight * 0.6 }; } function usePaneSize(t0) { const $ = c(7), { visionRootRef } = t0, [isNarrowBreakpoint, setIsNarrowBreakpoint] = useState(_temp$3), [paneSizeOptions, setPaneSizeOptions] = useState(_temp2$1); let t1; $[0] !== visionRootRef.current ? (t1 = () => { if (!visionRootRef.current) return; const handleResize = (entries) => { setIsNarrowBreakpoint(narrowBreakpoint()); const entry = entries?.[0]; entry && setPaneSizeOptions(calculatePaneSizeOptions(entry.contentRect.height)); }, resizeObserver = new ResizeObserver(handleResize); return resizeObserver.observe(visionRootRef.current), () => { resizeObserver.disconnect(); }; }, $[0] = visionRootRef.current, $[1] = t1) : t1 = $[1]; let t2; $[2] !== visionRootRef ? (t2 = [visionRootRef], $[2] = visionRootRef, $[3] = t2) : t2 = $[3], useEffect(t1, t2); let t3; return $[4] !== isNarrowBreakpoint || $[5] !== paneSizeOptions ? (t3 = { paneSizeOptions, isNarrowBreakpoint }, $[4] = isNarrowBreakpoint, $[5] = paneSizeOptions, $[6] = t3) : t3 = $[6], t3; } function _temp2$1() { return calculatePaneSizeOptions(void 0); } function _temp$3() { return narrowBreakpoint(); } function VisionGuiControls(t0) { const $ = c(30), { hasValidParams, listenInProgress, queryInProgress, onQueryExecution, onListenExecution } = t0, { t } = useTranslation(visionLocaleNamespace); let t1; $[0] !== t ? (t1 = t("params.error.params-invalid-json"), $[0] = t, $[1] = t1) : t1 = $[1]; let t2; $[2] !== t1 ? (t2 = /* @__PURE__ */ jsx(Card, { radius: 4, children: /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: t1 }) }), $[2] = t1, $[3] = t2) : t2 = $[3]; let t3; $[4] === Symbol.for("react.memo_cache_sentinel") ? (t3 = /* @__PURE__ */ jsx(Card, { radius: 4, children: /* @__PURE__ */ jsx(Hotkeys, { keys: ["Ctrl", "Enter"] }) }), $[4] = t3) : t3 = $[4]; const t4 = queryInProgress ? StopIcon : PlayIcon, t5 = listenInProgress || !hasValidParams, t6 = queryInProgress ? "positive" : "primary"; let t7; $[5] !== queryInProgress || $[6] !== t ? (t7 = t(queryInProgress ? "action.query-cancel" : "action.query-execute"), $[5] = queryInProgress, $[6] = t, $[7] = t7) : t7 = $[7]; let t8; $[8] !== onQueryExecution || $[9] !== t4 || $[10] !== t5 || $[11] !== t6 || $[12] !== t7 ? (t8 = /* @__PURE__ */ jsx(Box, { flex: 1, children: /* @__PURE__ */ jsx(Tooltip, { content: t3, placement: "top", portal: !0, children: /* @__PURE__ */ jsx(Button, { width: "fill", onClick: onQueryExecution, type: "button", icon: t4, disabled: t5, tone: t6, text: t7 }) }) }), $[8] = onQueryExecution, $[9] = t4, $[10] = t5, $[11] = t6, $[12] = t7, $[13] = t8) : t8 = $[13]; const t9 = listenInProgress ? StopIcon : PlayIcon; let t10; $[14] !== listenInProgress || $[15] !== t ? (t10 = t(listenInProgress ? "action.listen-cancel" : "action.listen-execute"), $[14] = listenInProgress, $[15] = t, $[16] = t10) : t10 = $[16]; const t11 = !hasValidParams, t12 = listenInProgress ? "positive" : "default"; let t13; $[17] !== onListenExecution || $[18] !== t10 || $[19] !== t11 || $[20] !== t12 || $[21] !== t9 ? (t13 = /* @__PURE__ */ jsx(Box, { flex: 1, marginLeft: 3, children: /* @__PURE__ */ jsx(Button, { width: "fill", onClick: onListenExecution, type: "button", icon: t9, text: t10, mode: "ghost", disabled: t11, tone: t12 }) }), $[17] = onListenExecution, $[18] = t10, $[19] = t11, $[20] = t12, $[21] = t9, $[22] = t13) : t13 = $[22]; let t14; $[23] !== t13 || $[24] !== t8 ? (t14 = /* @__PURE__ */ jsxs(Flex, { justify: "space-evenly", children: [ t8, t13 ] }), $[23] = t13, $[24] = t8, $[25] = t14) : t14 = $[25]; let t15; return $[26] !== hasValidParams || $[27] !== t14 || $[28] !== t2 ? (t15 = /* @__PURE__ */ jsx(ControlsContainer, { children: /* @__PURE__ */ jsx(Card, { padding: 3, paddingX: 3, children: /* @__PURE__ */ jsx(Tooltip, { content: t2, placement: "top", disabled: hasValidParams, portal: !0, children: t14 }) }) }), $[26] = hasValidParams, $[27] = t14, $[28] = t2, $[29] = t15) : t15 = $[29], t15; } const PerspectivePopoverContent = styled(Box)` /* This limits the width of the popover content */ max-width: 240px; `, PerspectivePopoverLink = styled.a` cursor: pointer; margin-right: auto; `, Dot = styled.div` width: 4px; height: 4px; border-radius: 3px; box-shadow: 0 0 0 1px var(--card-bg-color); background-color: ${({ tone }) => `var(--card-badge-${tone}-dot-color)`}; `; function PerspectivePopover() { const $ = c(39), [open, setOpen] = useState(!1), buttonRef = useRef(null), popoverRef = useRef(null); let t0; $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = () => setOpen(_temp$2), $[0] = t0) : t0 = $[0]; const handleClick = t0, { t } = useTranslation(visionLocaleNamespace); let t1, t2; $[1] === Symbol.for("react.memo_cache_sentinel") ? (t1 = () => setOpen(!1), t2 = () => [buttonRef.current, popoverRef.current], $[1] = t1, $[2] = t2) : (t1 = $[1], t2 = $[2]), useClickOutsideEvent(t1, t2); let t3; $[3] !== t ? (t3 = t("settings.perspectives.title"), $[3] = t, $[4] = t3) : t3 = $[4]; let t4; $[5] !== t3 ? (t4 = /* @__PURE__ */ jsx(Inline, { space: 2, children: /* @__PURE__ */ jsx(Text, { weight: "medium", children: t3 }) }), $[5] = t3, $[6] = t4) : t4 = $[6]; let t5; $[7] !== t ? (t5 = t("settings.perspectives.description"), $[7] = t, $[8] = t5) : t5 = $[8]; let t6; $[9] !== t5 ? (t6 = /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(Text, { muted: !0, children: t5 }) }), $[9] = t5, $[10] = t6) : t6 = $[10]; let t7; $[11] !== t ? (t7 = t("label.new"), $[11] = t, $[12] = t7) : t7 = $[12]; let t8; $[13] !== t7 ? (t8 = /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Badge, { tone: "primary", children: t7 }) }), $[13] = t7, $[14] = t8) : t8 = $[14]; let t9; $[15] !== t ? (t9 = /* @__PURE__ */ jsx(Text, { muted: !0, children: /* @__PURE__ */ jsx(Translate, { t, i18nKey: "settings.perspective.preview-drafts-renamed-to-drafts.description" }) }), $[15] = t, $[16] = t9) : t9 = $[16]; let t10; $[17] !== t8 || $[18] !== t9 ? (t10 = /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Stack, { space: 2, children: [ t8, t9 ] }) }), $[17] = t8, $[18] = t9, $[19] = t10) : t10 = $[19]; let t11; $[20] !== t ? (t11 = null, $[20] = t, $[21] = t11) : t11 = $[21]; let t12; $[22] !== t ? (t12 = t("settings.perspectives.action.docs-link"), $[22] = t, $[23] = t12) : t12 = $[23]; let t13; $[24] !== t12 ? (t13 = /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(Text, { children: /* @__PURE__ */ jsxs(PerspectivePopoverLink, { href: "https://sanity.io/docs/perspectives", target: "_blank", children: [ t12, " \u2192" ] }) }) }), $[24] = t12, $[25] = t13) : t13 = $[25]; let t14; $[26] !== t10 || $[27] !== t11 || $[28] !== t13 || $[29] !== t4 || $[30] !== t6 ? (t14 = /* @__PURE__ */ jsx(PerspectivePopoverContent, { children: /* @__PURE__ */ jsxs(Stack, { space: 4, children: [ t4, t6, t10, t11, t13 ] }) }), $[26] = t10, $[27] = t11, $[28] = t13, $[29] = t4, $[30] = t6, $[31] = t14) : t14 = $[31]; let t15; $[32] === Symbol.for("react.memo_cache_sentinel") ? (t15 = /* @__PURE__ */ jsx(Dot, { tone: "primary" }), $[32] = t15) : t15 = $[32]; let t16; $[33] !== open ? (t16 = /* @__PURE__ */ jsx(Button, { icon: HelpCircleIcon, mode: "bleed", padding: 2, paddingRight: 1, tone: "primary", fontSize: 1, ref: buttonRef, onClick: handleClick, selected: open, children: t15 }), $[33] = open, $[34] = t16) : t16 = $[34]; let t17; return $[35] !== open || $[36] !== t14 || $[37] !== t16 ? (t17 = /* @__PURE__ */ jsx(Popover, { content: t14, placement: "bottom-start", portal: !0, padding: 3, ref: popoverRef, open, children: t16 }), $[35] = open, $[36] = t14, $[37] = t16, $[38] = t17) : t17 = $[38], t17; } function _temp$2(o) { return !o; } const PinnedReleasePerspectiveOption = (t0) => { const $ = c(9), { pinnedPerspective, t } = t0, name = typeof pinnedPerspective.selectedPerspective == "object" ? pinnedPerspective.selectedPerspective.metadata.title : pinnedPerspective.selectedPerspectiveName; let t1; $[0] !== pinnedPerspective || $[1] !== t ? (t1 = hasPinnedPerspective(pinnedPerspective) ? `(${t("settings.perspectives.pinned-release-label")})` : t("settings.perspectives.pinned-release-label"), $[0] = pinnedPerspective, $[1] = t, $[2] = t1) : t1 = $[2]; const label = t1; let t2, t3; $[3] !== label || $[4] !== name ? (t3 = [name, label].filter(_temp$1), $[3] = label, $[4] = name, $[5] = t3) : t3 = $[5], t2 = t3.join(" "); const text = t2, t4 = !hasPinnedPerspective(pinnedPerspective); let t5; return $[6] !== t4 || $[7] !== text ? (t5 = /* @__PURE__ */ jsx("option", { value: "pinnedRelease", disabled: t4, children: text }), $[6] = t4, $[7] = text, $[8] = t5) : t5 = $[8], t5; }; function VisionGuiHeader(t0) { const $ = c(64), { onChangeDataset, dataset, customApiVersion, apiVersion, onChangeApiVersion, datasets, customApiVersionElementRef, onCustomApiVersionChange, isValidApiVersion, onChangePerspective, url, perspective } = t0, pinnedPerspective = usePerspective(), { t } = useTranslation(visionLocaleNamespace), operationUrlElement = useRef(null); let t1; $[0] === Symbol.for("react.memo_cache_sentinel") ? (t1 = () => { const el = operationUrlElement.current; if (el) try { el.select(), document.execCommand("copy"); } catch { console.error("Unable to copy to clipboard :("); } }, $[0] = t1) : t1 = $[0]; const handleCopyUrl = t1; let t2; $[1] === Symbol.for("react.memo_cache_sentinel") ? (t2 = [1, 4, 8, 12], $[1] = t2) : t2 = $[1]; let t3; $[2] !== t ? (t3 = t("settings.dataset-label"), $[2] = t, $[3] = t3) : t3 = $[3]; let t4; $[4] !== t3 ? (t4 = /* @__PURE__ */ jsx(Card, { paddingTop: 2, paddingBottom: 3, children: /* @__PURE__ */ jsx(StyledLabel, { children: t3 }) }), $[4] = t3, $[5] = t4) : t4 = $[5]; let t5; $[6] !== datasets ? (t5 = datasets.map(_temp2), $[6] = datasets, $[7] = t5) : t5 = $[7]; let t6; $[8] !== dataset || $[9] !== onChangeDataset || $[10] !== t5 ? (t6 = /* @__PURE__ */ jsx(Select, { value: dataset, onChange: onChangeDataset, children: t5 }), $[8] = dataset, $[9] = onChangeDataset, $[10] = t5, $[11] = t6) : t6 = $[11]; let t7; $[12] !== t4 || $[13] !== t6 ? (t7 = /* @__PURE__ */ jsx(Box, { padding: 1, column: 2, children: /* @__PURE__ */ jsxs(Stack, { children: [ t4, t6 ] }) }), $[12] = t4, $[13] = t6, $[14] = t7) : t7 = $[14]; let t8; $[15] !== t ? (t8 = t("settings.api-version-label"), $[15] = t, $[16] = t8) : t8 = $[16]; let t9; $[17] !== t8 ? (t9 = /* @__PURE__ */ jsx(Card, { paddingTop: 2, paddingBottom: 3, children: /* @__PURE__ */ jsx(StyledLabel, { children: t8 }) }), $[17] = t8, $[18] = t9) : t9 = $[18]; const t10 = customApiVersion === !1 ? apiVersion : "other"; let t11; $[19] === Symbol.for("react.memo_cache_sentinel") ? (t11 = API_VERSIONS.map(_temp3), $[19] = t11) : t11 = $[19]; let t12; $[20] !== t ? (t12 = t("settings.other-api-version-label"), $[20] = t, $[21] = t12) : t12 = $[21]; let t13; $[22] !== t12 ? (t13 = /* @__PURE__ */ jsx("option", { value: "other", children: t12 }, "other"), $[22] = t12, $[23] = t13) : t13 = $[23]; let t14; $[24] !== onChangeApiVersion || $[25] !== t10 || $[26] !== t13 ? (t14 = /* @__PURE__ */ jsxs(Select, { "data-testid": "api-version-selector", value: t10, onChange: onChangeApiVersion, children: [ t11, t13 ] }), $[24] = onChangeApiVersion, $[25] = t10, $[26] = t13, $[27] = t14) : t14 = $[27]; let t15; $[28] !== t14 || $[29] !== t9 ? (t15 = /* @__PURE__ */ jsx(Box, { padding: 1, column: 2, children: /* @__PURE__ */ jsxs(Stack, { children: [ t9, t14 ] }) }), $[28] = t14, $[29] = t9, $[30] = t15) : t15 = $[30]; let t16; $[31] !== customApiVersion || $[32] !== customApiVersionElementRef || $[33] !== isValidApiVersion || $[34] !== onCustomApiVersionChange || $[35] !== t ? (t16 = customApiVersion !== !1 && /* @__PURE__ */ jsx(Box, { padding: 1, column: 2, children: /* @__PURE__ */ jsxs(Stack, { children: [ /* @__PURE__ */ jsx(Card, { paddingTop: 2, paddingBottom: 3, children: /* @__PURE__ */ jsx(StyledLabel, { textOverflow: "ellipsis", children: t("settings.custom-api-version-label") }) }), /* @__PURE__ */ jsx(TextInput, { ref: customApiVersionElementRef, value: customApiVersion, onChange: onCustomApiVersionChange, customValidity: isValidApiVersion ? void 0 : t("settings.error.invalid-api-version"), maxLength: 11 }) ] }) }), $[31] = customApiVersion, $[32] = customApiVersionElementRef, $[33] = isValidApiVersion, $[34] = onCustomApiVersionChange, $[35] = t, $[36] = t16) : t16 = $[36]; let t17; $[37] !== t ? (t17 = t("settings.perspective-label"), $[37] = t, $[38] = t17) : t17 = $[38]; let t18; $[39] !== t17 ? (t18 = /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(StyledLabel, { children: t17 }) }), $[39] = t17, $[40] = t18) : t18 = $[40]; let t19; $[41] === Symbol.for("react.memo_cache_sentinel") ? (t19 = /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(PerspectivePopover, {}) }), $[41] = t19) : t19 = $[41]; let t20; $[42] !== t18 ? (t20 = /* @__PURE__ */ jsx(Card, { paddingBottom: 1, children: /* @__PURE__ */ jsxs(Inline, { space: 1, children: [ t18, t19 ] }) }), $[42] = t18, $[43] = t20) : t20 = $[43]; const t21 = perspective || "default"; let t22; $[44] !== pinnedPerspective || $[45] !== t ? (t22 = SUPPORTED_PERSPECTIVES.map((perspectiveName) => perspectiveName === "pinnedRelease" ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PinnedReleasePerspectiveOption, { pinnedPerspective, t }), /* @__PURE__ */ jsx("option", { value: "default", children: t("settings.perspectives.default") }, "default"), /* @__PURE__ */ jsx("hr", {}) ] }, "pinnedRelease") : /* @__PURE__ */ jsx("option", { children: perspectiveName }, perspectiveName)), $[44] = pinnedPerspective, $[45] = t, $[46] = t22) : t22 = $[46]; let t23; $[47] !== onChangePerspective || $[48] !== t21 || $[49] !== t22 ? (t23 = /* @__PURE__ */ jsx(Select, { value: t21, onChange: onChangePerspective, children: t22 }), $[47] = onChangePerspective, $[48] = t21, $[49] = t22, $[50] = t23) : t23 = $[50]; let t24; $[51] !== t20 || $[52] !== t23 ? (t24 = /* @__PURE__ */ jsx(Box, { padding: 1, column: 2, children: /* @__PURE__ */ jsxs(Stack, { children: [ t20, t23 ] }) }), $[51] = t20, $[52] = t23, $[53] = t24) : t24 = $[53]; let t25; $[54] !== customApiVersion || $[55] !== t || $[56] !== url ? (t25 = typeof url == "string" ? /* @__PURE__ */ jsx(Box, { padding: 1, flex: 1, column: customApiVersion === !1 ? 6 : 4, children: /* @__PURE__ */ jsxs(Stack, { children: [ /* @__PURE__ */ jsx(Card, { paddingTop: 2, paddingBottom: 3, children: /* @__PURE__ */ jsxs(StyledLabel, { children: [ t("query.url"), "\xA0", /* @__PURE__ */ jsxs(QueryCopyLink, { onClick: handleCopyUrl, children: [ "[", t("action.copy-url-to-clipboard"), "]" ] }) ] }) }), /* @__PURE__ */ jsxs(Flex, { flex: 1, gap: 1, children: [ /* @__PURE__ */ jsx(Box, { flex: 1, children: /* @__PURE__ */ jsx(TextInput, { readOnly: !0, type: "url", ref: operationUrlElement, value: url }) }), /* @__PURE__ */ jsx(Tooltip, { content: t("action.copy-url-to-clipboard"), children: /* @__PURE__ */ jsx(Button, { "aria-label": t("action.copy-url-to-clipboard"), type: "button", mode: "ghost", icon: CopyIcon, onClick: handleCopyUrl }) }) ] }) ] }) }) : /* @__PURE__ */ jsx(Box, { flex: 1 }), $[54] = customApiVersion, $[55] = t, $[56] = url, $[57] = t25) : t25 = $[57]; let t26; return $[58] !== t15 || $[59] !== t16 || $[60] !== t24 || $[61] !== t25 || $[62] !== t7 ? (t26 = /* @__PURE__ */ jsx(Header, { paddingX: 3, paddingY: 2, children: /* @__PURE__ */ jsxs(Grid, { columns: t2, children: [ t7, t15, t16, t24, t25 ] }) }), $[58] = t15, $[59] = t16, $[60] = t24, $[61] = t25, $[62] = t7, $[63] = t26) : t26 = $[63], t26; } function _temp3(version) { return /* @__PURE__ */ jsx("option", { children: version }, version); } function _temp2(ds) { return /* @__PURE__ */ jsx("option", { children: ds }, ds); } function _temp$1(value) { return typeof value < "u"; } function getBlobUrl(content, mimeType) { return URL.createObjectURL(new Blob([content], { type: mimeType })); } function getMemoizedBlobUrlResolver(mimeType, stringEncoder) { return /* @__PURE__ */ (() => { let prevResult = "", prevContent = ""; return (input) => { const content = stringEncoder(input); if (!(typeof content != "string" || content === "")) return content === prevContent || (prevContent = content, prevResult && URL.revokeObjectURL(prevResult), prevResult = getBlobUrl(content, mimeType)), prevResult; }; })(); } const getJsonBlobUrl = getMemoizedBlobUrlResolver("application/json", (input) => JSON.stringify(input, null, 2)), getCsvBlobUrl = getMemoizedBlobUrlResolver("text/csv", (input) => json2csv(Array.isArray(input) ? input : [input]).trim()), ErrorCode = styled(Code)` color: ${({ theme }) => theme.sanity.color.muted.critical.enabled.fg}; `; function QueryErrorDetails(t0) { const $ = c(7), { error } = t0, { t } = useTranslation(visionLocaleNamespace); if (!("details" in error)) return null; const details = { ...error.details, ...mapToLegacyDetails(error.details) }; if (!details.line) return null; const t1 = `${details.line} ${dashLine(details.column, details.columnEnd)}`; let t2; $[0] !== t1 ? (t2 = /* @__PURE__ */ jsx(ErrorCode, { size: 1, children: t1 }), $[0] = t1, $[1] = t2) : t2 = $[1]; const t3 = `${t("query.error.line")}: ${details.lineNumber} ${t("query.error.column")}: ${details.column}`; let t4; $[2] !== t3 ? (t4 = /* @__PURE__ */ jsx(Box, { marginTop: 4, children: /* @__PURE__ */ jsx(ErrorCode, { size: 1, children: t3 }) }), $[2] = t3, $[3] = t4) : t4 = $[3]; let t5; return $[4] !== t2 || $[5] !== t4 ? (t5 = /* @__PURE__ */ jsxs("div", { children: [ t2, t4 ] }), $[4] = t2, $[5] = t4, $[6] = t5) : t5 = $[6], t5; } function mapToLegacyDetails(details) { if (!details || typeof details.query != "string" || typeof details.start != "number") return {}; const { query, start, end } = details, lineStart = query.slice(0, start).lastIndexOf(` `) + 1, lineNumber = (query.slice(0, lineStart).match(/\n/g) || []).length, line = query.slice(lineStart, query.indexOf(` `, lineStart)), column = start - lineStart, columnEnd = typeof end == "number" ? end - lineStart : void 0; return { line, lineNumber, column, columnEnd }; } function dashLine(column, columnEnd) { const line = "-".repeat(column), hats = "^".repeat(columnEnd ? columnEnd - column : 1); return `${line}${hats}`; } function QueryErrorDialog(props) { const $ = c(7); let t0; $[0] !== props.error.message ? (t0 = /* @__PURE__ */ jsx(ErrorCode, { size: 1, children: props.error.message }), $[0] = props.error.message, $[1] = t0) : t0 = $[1]; let t1; $[2] !== props.error ? (t1 = /* @__PURE__ */ jsx(QueryErrorDetails, { error: props.error }), $[2] = props.error, $[3] = t1) : t1 = $[3]; let t2; return $[4] !== t0 || $[5] !== t1 ? (t2 = /* @__PURE__ */ jsxs(Stack, { space: 5, marginTop: 2, children: [ t0, t1 ] }), $[4] = t0, $[5] = t1, $[6] = t2) : t2 = $[6], t2; } const ResultViewWrapper = styled.div(({ theme }) => { const { color, fonts, space } = theme.sanity; return css` & .json-inspector, & .json-inspector .json-inspector__selection { font-family: ${fonts.code.family}; font-size: ${fonts.code.sizes[2].fontSize}px; line-height: ${fonts.code.sizes[2].lineHeight}px; color: var(--card-code-fg-color); } & .json-inspector .json-inspector__leaf { padding-left: ${rem(space[4])}; } & .json-inspector .json-inspector__leaf.json-inspector__leaf_root { padding-top: ${rem(space[0])}; padding-left: 0; } & .json-inspector > .json-inspector__leaf_root > .json-inspector__line > .json-inspector__key { display: none; } & .json-inspector .json-inspector__line { display: block; position: relative; cursor: default; } & .json-inspector .json-inspector__line::after { content: ''; position: absolute; top: 0; left: -200px; right: -50px; bottom: 0; z-index: -1; pointer-events: none; } & .json-inspector .json-inspector__line:hover::after { background: var(--card-code-bg-color); } & .json-inspector .json-inspector__leaf_composite > .json-inspector__line { cursor: pointer; } & .json-inspector .json-inspector__leaf_composite > .json-inspector__line::before { content: '▸ '; margin-left: calc(0px - ${rem(space[4])}); font-size: ${fonts.code.sizes[2].fontSize}px; line-height: ${fonts.code.sizes[2].lineHeight}px; } & .json-inspector .json-inspector__leaf_expanded.json-inspector__leaf_composite > .json-inspector__line::before { content: '▾ '; font-size: ${fonts.code.sizes[2].fontSize}px; line-height: ${fonts.code.sizes[2].lineHeight}px; } & .json-inspector .json-inspector__radio, & .json-inspector .json-inspector__flatpath { display: none; } & .json-inspector .json-inspector__value { margin-left: ${rem(space[4] / 2)}; } & .json-inspector > .json-inspector__leaf_root > .json-inspector__line > .json-inspector__key + .json-inspector__value { margin: 0; } & .json-inspector .json-inspector__key { color: ${color.syntax.property}; } & .json-inspector .json-inspector__value_helper, & .json-inspector .json-inspector__value_null { color: ${color.syntax.constant}; } & .json-inspector .json-inspector__not-found { padding-top: ${rem(space[2])}; } & .json-inspector .json-inspector__value_string { color: ${color.syntax.string}; word-break: break-word; } & .json-inspector .json-inspector__value_boolean { color: ${color.syntax.boolean}; } & .json-inspector .json-inspector__value_number { color: ${color.syntax.number}; } & .json-inspector .json-inspector__show-original { display: inline-block; padding: 0 6px; cursor: pointer; } & .json-inspector .json-inspector__show-original:hover { color: inherit; } & .json-inspector .json-inspector__show-original::before { content: '↔'; } & .json-inspector .json-inspector__show-original:hover::after { content: ' expand'; } `; }), lru = new LRU({ maxSize: 5e4 }); function ResultView(props) { const $ = c(7), { data, datasetName } = props, workspaceDataset = useDataset(); if (isRecord(data) || Array.isArray(data)) { const t02 = workspaceDataset === datasetName ? DocumentEditLabel : void 0; let t12; return $[0] !== data || $[1] !== t02 ? (t12 = /* @__PURE__ */ jsx(ResultViewWrapper, { children: /* @__PURE__ */ jsx(JsonInspector, { data, search: !1, isExpanded, onClick: toggleExpanded, interactiveLabel: t02 }) }), $[0] = data, $[1] = t02, $[2] = t12) : t12 = $[2], t12; } let t0; $[3] !== data ? (t0 = JSON.stringify(data), $[3] = data, $[4] = t0) : t0 = $[4]; let t1; return $[5] !== t0 ? (t1 = /* @__PURE__ */ jsx(Code, { language: "json", children: t0 }), $[5] = t0, $[6] = t1) : t1 = $[6], t1; } function DocumentEditLabel(props) { const $ = c(5); if (props.isKey || !props.keypath.endsWith("_id") && !props.keypath.endsWith("_ref")) return null; let t0; $[0] !== props.value ? (t0 = { id: props.value }, $[0] = props.value, $[1] = t0) : t0 = $[1]; let t1; $[2] === Symbol.for("react.memo_cache_sentinel") ? (t1 = /* @__PURE__ */ jsx(LinkIcon, {}), $[2] = t1) : t1 = $[2]; let t2; return $[3] !== t0 ? (t2 = /* @__PURE__ */ jsx(IntentLink, { intent: "edit", params: t0, children: t1 }), $[3] = t0, $[4] = t2) : t2 = $[4], t2; } function isExpanded(keyPath, value) { const cached = lru.get(keyPath); if (typeof cached == "boolean") return cached; const segments = keyPath.split(".", 4); return segments.length === 4 ? !1 : Array.isArray(value) ? !0 : isRecord(value) && !segments.some((key) => isArrayKeyOverLimit(key)); } function toggleExpanded(event) { const { path } = event, current = lru.get(path); current !== void 0 && lru.set(path, !current); } function isRecord(value) { return value !== null && typeof value == "object" && !Array.isArray(value); } const numeric = /^\d+$/; function isArrayKeyOverLimit(segment, limit = 10) { return numeric.test(segment) && parseInt(segment, 10) > limit; } function preventSave(evt) { return evt.preventDefault(); } function SaveCsvButton(t0) { const $ = c(9), { blobUrl } = t0, { t } = useTranslation(visionLocaleNamespace), isDisabled = !blobUrl, t1 = isDisabled ? void 0 : "query-result.csv", t2 = isDisabled ? preventSave : void 0; let t3; $[0] !== blobUrl || $[1] !== isDisabled || $[2] !== t1 || $[3] !== t2 ? (t3 = /* @__PURE__ */ jsx(Button, { as: "a", disabled: isDisabled, download: t1, href: blobUrl, icon: DocumentSheetIcon, mode: "ghost", onClick: t2, text: "CSV", tone: "default" }), $[0] = blobUrl, $[1] = isDisabled, $[2] = t1, $[3] = t2, $[4] = t3) : t3 = $[4]; const button = t3; let t4; return $[5] !== button || $[6] !== isDisabled || $[7] !== t ? (t4 = isDisabled ? /* @__PURE__ */ jsx(Tooltip, { content: t("result.save-result-as-csv.not-csv-encodable"), placement: "top", children: button }) : button, $[5] = button, $[6] = isDisabled, $[7] = t, $[8] = t4) : t4 = $[8], t4; } function SaveJsonButton(t0) { const $ = c(2), { blobUrl } = t0; let t1; return $[0] !== blobUrl ? (t1 = /* @__PURE__ */ jsx(Button, { as: "a", download: "query-result.json", href: blobUrl, icon: DocumentSheetIcon, mode: "ghost", text: "JSON", tone: "default" }), $[0] = blobUrl, $[1] = t1) : t1 = $[1], t1; } function VisionGuiResult(t0) { const $ = c(67), { error, queryInProgress, queryResult, listenInProgress, listenMutations, dataset, queryTime, e2eTime } = t0, { t } = useTranslation(visionLocaleNamespace), hasResult = !error && !queryInProgress && typeof queryResult < "u"; let t1; $[0] !== hasResult || $[1] !== queryResult ? (t1 = hasResult ? getJsonBlobUrl(queryResult) : "", $[0] = hasResult, $[1] = queryResult, $[2] = t1) : t1 = $[2]; const jsonUrl = t1; let t2; $[3] !== hasResult || $[4] !== queryResult ? (t2 = hasResult ? getCsvBlobUrl(queryResult) : "", $[3] = hasResult, $[4] = queryResult, $[5] = t2) : t2 = $[5]; const csvUrl = t2, t3 = error ? "critical" : "default", t4 = !!error; let t5; $[6] !== t ? (t5 = t("result.label"), $[6] = t, $[7] = t5) : t5 = $[7]; let t6; $[8] !== t5 ? (t6 = /* @__PURE__ */ jsx(InputBackgroundContainer, { children: /* @__PURE__ */ jsx(Box, { marginLeft: 3, children: /* @__PURE__ */ jsx(StyledLabel, { muted: !0, children: t5 }) }) }), $[8] = t5, $[9] = t6) : t6 = $[9]; let t7; $[10] !== listenInProgress || $[11] !== listenMutations || $[12] !== queryInProgress ? (t7 = (queryInProgress || listenInProgress && listenMutations.length === 0) && /* @__PURE__ */ jsx(Box, { marginTop: 3, children: /* @__PURE__ */ jsx(DelayedSpinner, {}) }), $[10] = listenInProgress, $[11] = listenMutations, $[12] = queryInProgress, $[13] = t7) : t7 = $[13]; let t8; $[14] !== error ? (t8 = error && /* @__PURE__ */ jsx(QueryErrorDialog, { error }), $[14] = error, $[15] = t8) : t8 = $[15]; let t9; $[16] !== dataset || $[17] !== hasResult || $[18] !== queryResult ? (t9 = hasResult && /* @__PURE__ */ jsx(ResultView, { data: queryResult, datasetName: dataset }), $[16] = dataset, $[17] = hasResult, $[18] = queryResult, $[19] = t9) : t9 = $[19]; let t10; $[20] !== dataset || $[21] !== listenInProgress || $[22] !== listenMutations ? (t10 = listenInProgress && listenMutations.length > 0 && /* @__PURE__ */ jsx(ResultView, { data: listenMutations, datasetName: dataset }), $[20] = dataset, $[21] = listenInProgress, $[22] = listenMutations, $[23] = t10) : t10 = $[23]; let t11; $[24] !== t10 || $[25] !== t7 || $[26] !== t8 || $[27] !== t9 ? (t11 = /* @__PURE__ */ jsxs(Box, { padding: 3, paddingTop: 5, children: [ t7, t8, t9, t10 ] }), $[24] = t10, $[25] = t7, $[26] = t8, $[27] = t9, $[28] = t11) : t11 = $[28]; let t12; $[29] !== t11 || $[30] !== t6 ? (t12 = /* @__PURE__ */ jsxs(Result, { overflow: "auto", children: [ t6, t11 ] }), $[29] = t11, $[30] = t6, $[31] = t12) : t12 = $[31]; let t13; $[32] !== t12 || $[33] !== t3 || $[34] !== t4 ? (t13 = /* @__PURE__ */ jsx(ResultInnerContainer, { flex: 1, children: /* @__PURE__ */ jsx(ResultContainer, { flex: 1, overflow: "hidden", tone: t3, $isInvalid: t4, children: t12 }) }), $[32] = t12, $[33] = t3, $[34] = t4, $[35] = t13) : t13 = $[35]; let t14; $[36] === Symbol.for("react.memo_cache_sentinel") ? (t14 = ["column", "column", "row"], $[36] = t14) : t14 = $[36]; let t15; $[37] !== t ? (t15 = t("result.execution-time-label"), $[37] = t, $[38] = t15) : t15 = $[38]; let t16; $[39] !== queryTime || $[40] !== t ? (t16 = typeof queryTime == "number" ? `${queryTime}ms` : t("result.timing-not-applicable"), $[39] = queryTime, $[40] = t, $[41] = t16) : t16 = $[41]; let t17; $[42] !== t15 || $[43] !== t16 ? (t17 = /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { muted: !0, children: [ t15, ":", " ", t16 ] }) }), $[42] = t15, $[43] = t16, $[44] = t17) : t17 = $[44]; let t18; $[45] !== t ? (t18 = t("result.end-to-end-time-label"), $[45] = t, $[46] = t18) : t18 = $[46]; let t19; $[47] !== e2eTime || $[48] !== t ? (t19 = typeof e2eTime == "number" ? `${e2eTime}ms` : t("result.timing-not-applicable"), $[47] = e2eTime, $[48] = t, $[49] = t19) : t19 = $[49]; let t20; $[50] !== t18 || $[51] !== t19 ? (t20 = /* @__PURE__ */ jsx(Box, { marginLeft: 4, children: /* @__PURE__ */ jsxs(Text, { muted: !0, children: [ t18, ":", " ", t19 ] }) }), $[50] = t18, $[51] = t19, $[52] = t20) : t20 = $[52]; let t21; $[53] !== t17 || $[54] !== t20 ? (t21 = /* @__PURE__ */ jsx(TimingsCard, { paddingX: 4, paddingY: 3, sizing: "border", children: /* @__PURE__ */ jsxs(TimingsTextContainer, { align: "center", children: [ t17, t20 ] }) }), $[53] = t17, $[54] = t20, $[55] = t21) : t21 = $[55]; let t22; $[56] !== csvUrl || $[57] !== hasResult || $[58] !== jsonUrl || $[59] !== t ? (t22 = hasResult && /* @__PURE__ */ jsx(DownloadsCard, { paddingX: 4, paddingY: 3, sizing: "border", children: /* @__PURE__ */ jsx(SaveResultLabel, { muted: !0, children: /* @__PURE__ */ jsx(Translate, { components: { SaveResultButtons: () => /* @__PURE__ */ jsxs(Fragment$1, { children: [ /* @__PURE__ */ jsx(SaveJsonButton, { blobUrl: jsonUrl }), /* @__PURE__ */ jsx(SaveCsvButton, { blobUrl: csvUrl }) ] }) }, i18nKey: "result.save