@sanity/vision
Version:
Sanity plugin for running/debugging GROQ-queries against Sanity datasets
1,185 lines (1,148 loc) • 69.8 kB
JavaScript
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