UNPKG

@sanity/vision

Version:

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

1,124 lines (1,106 loc) • 100 kB
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime"; import { c } from "react/compiler-runtime"; import { useTranslation, useKeyValueStore, useDateTimeFormat, ContextMenuButton, Translate, usePerspective, useDataset, useScheduledDraftsEnabled, useActiveReleases, useWorkspace, sortReleases, useClient, isCardinalityOneRelease, getReleaseIdFromReleaseDocumentId } from "sanity"; import { Spinner, rem, useTheme, Flex, Card, Label, Box, Text, Tooltip, Stack, useToast, TextInput, MenuButton, Menu, MenuItem, Code, Button, Hotkeys, useClickOutsideEvent, Popover, Inline, Badge, Grid, Select, Container, Heading } from "@sanity/ui"; import { useState, useEffect, forwardRef, useRef, useImperativeHandle, Fragment, useEffectEvent, Component } from "react"; import { SplitPane } from "@rexxars/react-split-pane"; import { ErrorOutlineIcon, TrashIcon, AddIcon, SearchIcon, StopIcon, PlayIcon, HelpCircleIcon, CopyIcon, LinkIcon, DocumentSheetIcon, ChevronLeftIcon, ChevronRightIcon } from "@sanity/icons"; import { isHotkey } from "is-hotkey-esm"; 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.js"; import { debounce, isEqual } from "lodash-es"; import JSON5 from "json5"; import { uuid } from "@sanity/uuid"; import { startWith, map } from "rxjs/operators"; import { json2csv } from "json-2-csv"; import { JsonInspector } from "@rexxars/react-json-inspector"; import LRU from "quick-lru"; import { IntentLink } from "sanity/router"; import { useObservable } from "react-rx"; import { of, map as map$1, catchError } from "rxjs"; 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; $[0] !== theme ? (t0 = createTheme(theme), $[0] = theme, $[1] = t0) : t0 = $[1]; const cmTheme = t0; let t1; $[2] !== theme ? (t1 = syntaxHighlighting(createHighlight(theme)), $[2] = theme, $[3] = t1) : t1 = $[3]; const cmHighlight = t1; let t2; return $[4] !== cmHighlight || $[5] !== cmTheme ? (t2 = [cmTheme, cmHighlight], $[4] = cmHighlight, $[5] = cmTheme, $[6] = t2) : t2 = $[6], t2; } 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] === /* @__PURE__ */ 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] === /* @__PURE__ */ 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", "scheduledDrafts", "raw", "published", "drafts"], VIRTUAL_PERSPECTIVES = ["pinnedRelease", "scheduledDrafts"]; 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, scheduledDraftsStack }) { return visionPerspective === "pinnedRelease" ? perspectiveStack : visionPerspective === "scheduledDrafts" ? scheduledDraftsStack : visionPerspective; } 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$1 = `{ }`; function ParamsEditor(props) { const $ = c(21), { onChange, paramsError, hasValidParams, editorRef } = props, { t } = useTranslation(visionLocaleNamespace); let t0; $[0] !== onChange ? (t0 = (newValue) => { onChange(newValue); }, $[0] = onChange, $[1] = t0) : t0 = $[1]; const handleChangeRaw = t0; let t1; $[2] !== handleChangeRaw ? (t1 = debounce(handleChangeRaw, 333), $[2] = handleChangeRaw, $[3] = t1) : t1 = $[3]; const handleChange = t1, t2 = hasValidParams ? "default" : "critical"; let t3; $[4] !== t ? (t3 = t("params.label"), $[4] = t, $[5] = t3) : t3 = $[5]; let t4; $[6] !== t3 ? (t4 = /* @__PURE__ */ jsx(StyledLabel, { muted: !0, children: t3 }), $[6] = t3, $[7] = t4) : t4 = $[7]; let t5; $[8] !== paramsError ? (t5 = 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, {}) }) }) }), $[8] = paramsError, $[9] = t5) : t5 = $[9]; let t6; $[10] !== t4 || $[11] !== t5 ? (t6 = /* @__PURE__ */ jsx(InputBackgroundContainerLeft, { children: /* @__PURE__ */ jsxs(Flex, { children: [ t4, t5 ] }) }), $[10] = t4, $[11] = t5, $[12] = t6) : t6 = $[12]; const t7 = props.value || defaultValue$1; let t8; $[13] !== editorRef || $[14] !== handleChange || $[15] !== t7 ? (t8 = /* @__PURE__ */ jsx(VisionCodeMirror, { ref: editorRef, initialValue: t7, onChange: handleChange }), $[13] = editorRef, $[14] = handleChange, $[15] = t7, $[16] = t8) : t8 = $[16]; let t9; return $[17] !== t2 || $[18] !== t6 || $[19] !== t8 ? (t9 = /* @__PURE__ */ jsxs(Card, { flex: 1, tone: t2, "data-testid": "params-editor", children: [ t6, t8 ] }), $[17] = t2, $[18] = t6, $[19] = t8, $[20] = t9) : t9 = $[20], t9; } 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 }; } const STORED_QUERIES_NAMESPACE = "studio.vision-tool.saved-queries", defaultValue = { queries: [] }, keyValueStoreKey = STORED_QUERIES_NAMESPACE; function useSavedQueries() { const $ = c(27), keyValueStore = useKeyValueStore(), [value, setValue] = useState(defaultValue), [saving, setSaving] = useState(!1); let t0; $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = [], $[0] = t0) : t0 = $[0]; const [deleting, setDeleting] = useState(t0), [saveQueryError, setSaveQueryError] = useState(), [deleteQueryError, setDeleteQueryError] = useState(), [error, setError] = useState(); let t1; $[1] !== keyValueStore ? (t1 = keyValueStore.getKey(keyValueStoreKey), $[1] = keyValueStore, $[2] = t1) : t1 = $[2]; const queries = t1; let t2; $[3] !== queries ? (t2 = () => { const sub = queries.pipe(startWith(defaultValue), map(_temp$5)).subscribe({ next: setValue, error: (err) => setError(err) }); return () => sub?.unsubscribe(); }, $[3] = queries, $[4] = t2) : t2 = $[4]; let t3; $[5] !== keyValueStore || $[6] !== queries ? (t3 = [queries, keyValueStore], $[5] = keyValueStore, $[6] = queries, $[7] = t3) : t3 = $[7], useEffect(t2, t3); let t4; $[8] !== keyValueStore || $[9] !== value.queries ? (t4 = async (query) => { setSaving(!0), setSaveQueryError(void 0); try { const newQueries = [{ ...query, _key: uuid() }, ...value.queries]; setValue({ queries: newQueries }), await keyValueStore.setKey(keyValueStoreKey, { queries: newQueries }); } catch (t52) { setSaveQueryError(t52); } setSaving(!1); }, $[8] = keyValueStore, $[9] = value.queries, $[10] = t4) : t4 = $[10]; const saveQuery = t4; let t5; $[11] !== keyValueStore || $[12] !== value.queries ? (t5 = async (query_0) => { setSaving(!0), setSaveQueryError(void 0); try { const updatedQueries = value.queries.map((q) => q._key === query_0._key ? { ...q, ...query_0 } : q); setValue({ queries: updatedQueries }), await keyValueStore.setKey(keyValueStoreKey, { queries: updatedQueries }); } catch (t62) { setSaveQueryError(t62); } setSaving(!1); }, $[11] = keyValueStore, $[12] = value.queries, $[13] = t5) : t5 = $[13]; const updateQuery = t5; let t6; $[14] !== keyValueStore || $[15] !== value.queries ? (t6 = async (key) => { setDeleting((prev) => [...prev, key]), setDeleteQueryError(void 0); try { const filteredQueries = value.queries.filter((q_0) => q_0._key !== key); setValue({ queries: filteredQueries }), await keyValueStore.setKey(keyValueStoreKey, { queries: filteredQueries }); } catch (t72) { setDeleteQueryError(t72); } setDeleting((prev_0) => prev_0.filter((k) => k !== key)); }, $[14] = keyValueStore, $[15] = value.queries, $[16] = t6) : t6 = $[16]; const deleteQuery = t6; let t7; return $[17] !== deleteQuery || $[18] !== deleteQueryError || $[19] !== deleting || $[20] !== error || $[21] !== saveQuery || $[22] !== saveQueryError || $[23] !== saving || $[24] !== updateQuery || $[25] !== value.queries ? (t7 = { queries: value.queries, saveQuery, updateQuery, deleteQuery, saving, deleting, saveQueryError, deleteQueryError, error }, $[17] = deleteQuery, $[18] = deleteQueryError, $[19] = deleting, $[20] = error, $[21] = saveQuery, $[22] = saveQueryError, $[23] = saving, $[24] = updateQuery, $[25] = value.queries, $[26] = t7) : t7 = $[26], t7; } function _temp$5(data) { return data || defaultValue; } const FixedHeader = styled(Stack)` position: sticky; top: 0; background: ${({ theme }) => theme.sanity.color.base.bg}; z-index: 1; `, ScrollContainer = styled(Box)` height: 100%; overflow-y: auto; overflow-x: hidden; &::-webkit-scrollbar { width: 8px; } &::-webkit-scrollbar-track { background: transparent; } &::-webkit-scrollbar-thumb { background: ${({ theme }) => theme.sanity.color.base.border}; border-radius: 4px; } `; function QueryRecall(t0) { const $ = c(80), { url, getStateFromUrl, setStateFromParsedUrl, currentQuery, currentParams, generateUrl } = t0, toast = useToast(), { saveQuery, updateQuery, queries, deleteQuery, saving, saveQueryError } = useSavedQueries(), { t } = useTranslation(visionLocaleNamespace); let t1; $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = { month: "short", day: "numeric", year: "numeric", hour: "numeric", minute: "2-digit", hour12: !0 }, $[0] = t1) : t1 = $[0]; const formatDate = useDateTimeFormat(t1), [editingKey, setEditingKey] = useState(null), [editingTitle, setEditingTitle] = useState(""); let t2; $[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t2 = {}, $[1] = t2) : t2 = $[1]; const [optimisticTitles, setOptimisticTitles] = useState(t2), [searchQuery, setSearchQuery] = useState(""), [selectedUrl, setSelectedUrl] = useState(url); let t3; $[2] !== currentParams || $[3] !== currentQuery || $[4] !== formatDate || $[5] !== generateUrl || $[6] !== getStateFromUrl || $[7] !== queries || $[8] !== saveQuery || $[9] !== saveQueryError || $[10] !== t || $[11] !== toast ? (t3 = async () => { const newUrl = generateUrl(currentQuery, currentParams); if (queries?.some((q) => { const savedQueryObj = getStateFromUrl(q.url); return savedQueryObj && savedQueryObj.query === currentQuery && isEqual(savedQueryObj.params, currentParams); })) { const duplicateQuery = queries?.find((q_0) => { const savedQueryObj_0 = getStateFromUrl(q_0.url); return savedQueryObj_0 && savedQueryObj_0.query === currentQuery && isEqual(savedQueryObj_0.params, currentParams); }); toast.push({ closable: !0, status: "warning", title: t("save-query.already-saved"), description: `${duplicateQuery?.title} - ${formatDate.format(new Date(duplicateQuery?.savedAt || ""))}` }); return; } newUrl && (await saveQuery({ url: newUrl, savedAt: (/* @__PURE__ */ new Date()).toISOString(), title: "Untitled" }), setSelectedUrl(newUrl)), saveQueryError ? toast.push({ closable: !0, status: "error", title: t("save-query.error"), description: saveQueryError.message }) : toast.push({ closable: !0, status: "success", title: t("save-query.success") }); }, $[2] = currentParams, $[3] = currentQuery, $[4] = formatDate, $[5] = generateUrl, $[6] = getStateFromUrl, $[7] = queries, $[8] = saveQuery, $[9] = saveQueryError, $[10] = t, $[11] = toast, $[12] = t3) : t3 = $[12]; const handleSave = t3; let t4; $[13] !== t || $[14] !== toast || $[15] !== updateQuery ? (t4 = async (query, newTitle) => { setEditingKey(null), setOptimisticTitles((prev) => ({ ...prev, [query._key]: newTitle })); try { await updateQuery({ ...query, title: newTitle }), setOptimisticTitles((prev_1) => { const next_0 = { ...prev_1 }; return delete next_0[query._key], next_0; }); } catch (t52) { const err = t52; setOptimisticTitles((prev_0) => { const next = { ...prev_0 }; return delete next[query._key], next; }), toast.push({ closable: !0, status: "error", title: t("save-query.error"), description: err.message }); } }, $[13] = t, $[14] = toast, $[15] = updateQuery, $[16] = t4) : t4 = $[16]; const handleTitleSave = t4; let t5; $[17] !== currentParams || $[18] !== currentQuery || $[19] !== formatDate || $[20] !== generateUrl || $[21] !== getStateFromUrl || $[22] !== queries || $[23] !== t || $[24] !== toast || $[25] !== updateQuery ? (t5 = async (query_0) => { const newUrl_0 = generateUrl(currentQuery, currentParams); if (queries?.some((q_1) => { if (q_1._key === query_0._key) return !1; const savedQueryObj_1 = getStateFromUrl(q_1.url); return savedQueryObj_1 && savedQueryObj_1.query === currentQuery && isEqual(savedQueryObj_1.params, currentParams); })) { const duplicateQuery_0 = queries?.find((q_2) => { if (q_2._key === query_0._key) return !1; const savedQueryObj_2 = getStateFromUrl(q_2.url); return savedQueryObj_2 && savedQueryObj_2.query === currentQuery && isEqual(savedQueryObj_2.params, currentParams); }); toast.push({ closable: !0, status: "warning", title: t("save-query.already-saved"), description: `${duplicateQuery_0?.title} - ${formatDate.format(new Date(duplicateQuery_0?.savedAt || ""))}` }); return; } try { await updateQuery({ ...query_0, url: newUrl_0, savedAt: (/* @__PURE__ */ new Date()).toISOString() }), setSelectedUrl(newUrl_0), toast.push({ closable: !0, status: "success", title: t("save-query.success") }); } catch (t62) { const err_0 = t62; toast.push({ closable: !0, status: "error", title: t("save-query.error"), description: err_0.message }); } }, $[17] = currentParams, $[18] = currentQuery, $[19] = formatDate, $[20] = generateUrl, $[21] = getStateFromUrl, $[22] = queries, $[23] = t, $[24] = toast, $[25] = updateQuery, $[26] = t5) : t5 = $[26]; const handleUpdate = t5; let T0, T1, t6, t7, t8; if ($[27] !== currentParams || $[28] !== currentQuery || $[29] !== deleteQuery || $[30] !== editingKey || $[31] !== editingTitle || $[32] !== formatDate || $[33] !== getStateFromUrl || $[34] !== handleSave || $[35] !== handleTitleSave || $[36] !== handleUpdate || $[37] !== optimisticTitles || $[38] !== queries || $[39] !== saving || $[40] !== searchQuery || $[41] !== selectedUrl || $[42] !== setStateFromParsedUrl || $[43] !== t) { const filteredQueries = queries?.filter((q_3) => q_3?.title?.toLowerCase().includes(searchQuery.toLowerCase())); T1 = ScrollContainer; let t92; $[49] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t92 = { textTransform: "capitalize" }, $[49] = t92) : t92 = $[49]; let t102; $[50] !== t ? (t102 = t("label.saved-queries"), $[50] = t, $[51] = t102) : t102 = $[51]; let t11; $[52] !== t102 ? (t11 = /* @__PURE__ */ jsx(Text, { weight: "semibold", style: t92, size: 4, children: t102 }), $[52] = t102, $[53] = t11) : t11 = $[53]; let t12; $[54] !== t ? (t12 = t("action.save-query"), $[54] = t, $[55] = t12) : t12 = $[55]; let t13; $[56] !== handleSave || $[57] !== saving || $[58] !== t12 ? (t13 = /* @__PURE__ */ jsx(Button, { label: t12, icon: AddIcon, disabled: saving, onClick: handleSave, mode: "bleed" }), $[56] = handleSave, $[57] = saving, $[58] = t12, $[59] = t13) : t13 = $[59]; let t14; $[60] !== t11 || $[61] !== t13 ? (t14 = /* @__PURE__ */ jsxs(Flex, { padding: 3, paddingTop: 4, paddingBottom: 0, justify: "space-between", align: "center", children: [ t11, t13 ] }), $[60] = t11, $[61] = t13, $[62] = t14) : t14 = $[62]; let t15; $[63] !== t ? (t15 = t("label.search-queries"), $[63] = t, $[64] = t15) : t15 = $[64]; let t16; $[65] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t16 = (event) => setSearchQuery(event.currentTarget.value), $[65] = t16) : t16 = $[65]; let t17; $[66] !== searchQuery || $[67] !== t15 ? (t17 = /* @__PURE__ */ jsx(Box, { padding: 3, paddingTop: 0, children: /* @__PURE__ */ jsx(TextInput, { placeholder: t15, icon: SearchIcon, value: searchQuery, onChange: t16 }) }), $[66] = searchQuery, $[67] = t15, $[68] = t17) : t17 = $[68], $[69] !== t14 || $[70] !== t17 ? (t8 = /* @__PURE__ */ jsxs(FixedHeader, { space: 3, children: [ t14, t17 ] }), $[69] = t14, $[70] = t17, $[71] = t8) : t8 = $[71], T0 = Stack, t6 = 3, t7 = filteredQueries?.map((q_4) => { const queryObj = getStateFromUrl(q_4.url), isSelected = selectedUrl === q_4.url, areQueriesEqual = queryObj && currentQuery === queryObj.query && isEqual(currentParams, queryObj.params), isEdited = isSelected && !areQueriesEqual; return /* @__PURE__ */ jsx(Card, { width: "fill", padding: 4, border: !0, tone: isSelected ? "positive" : "default", onClick: () => { setSelectedUrl(q_4.url); const parsedUrl = getStateFromUrl(q_4.url); parsedUrl && setStateFromParsedUrl(parsedUrl); }, style: { position: "relative" }, children: /* @__PURE__ */ jsxs(Stack, { space: 3, children: [ /* @__PURE__ */ jsxs(Flex, { justify: "space-between", align: "center", children: [ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, paddingRight: 1, children: [ editingKey === q_4._key ? /* @__PURE__ */ jsx(TextInput, { value: editingTitle, onChange: (event_0) => setEditingTitle(event_0.currentTarget.value), onKeyDown: (event_1) => { event_1.key === "Enter" ? handleTitleSave(q_4, editingTitle) : event_1.key === "Escape" && setEditingKey(null); }, onBlur: () => handleTitleSave(q_4, editingTitle), autoFocus: !0, style: { maxWidth: "170px", height: "24px" } }) : /* @__PURE__ */ jsx(Text, { weight: "bold", size: 3, textOverflow: "ellipsis", style: { maxWidth: "170px", cursor: "pointer", padding: "4px 0" }, title: optimisticTitles[q_4._key] || q_4.title || q_4._key.slice(q_4._key.length - 5, q_4._key.length), onClick: () => { setEditingKey(q_4._key), setEditingTitle(q_4.title || q_4._key.slice(0, 5)); }, children: optimisticTitles[q_4._key] || q_4.title || q_4._key.slice(q_4._key.length - 5, q_4._key.length) }), isEdited && /* @__PURE__ */ jsx(Box, { style: { width: "6px", height: "6px", borderRadius: "50%", backgroundColor: "var(--card-focus-ring-color)" } }) ] }), /* @__PURE__ */ jsx(MenuButton, { button: /* @__PURE__ */ jsx(ContextMenuButton, {}), id: `${q_4._key}-menu`, menu: /* @__PURE__ */ jsx(Menu, { children: /* @__PURE__ */ jsx(MenuItem, { tone: "critical", padding: 3, icon: TrashIcon, text: t("action.delete"), onClick: (event_2) => { event_2.stopPropagation(), deleteQuery(q_4._key); } }) }), popover: { portal: !0, placement: "bottom-end", tone: "default" } }) ] }), /* @__PURE__ */ jsx(Code, { muted: !0, children: queryObj?.query.split("{")[0] }), /* @__PURE__ */ jsx(Flex, { align: "center", gap: 1, children: /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: formatDate.format(new Date(q_4.savedAt || "")) }) }), isEdited && /* @__PURE__ */ jsx(Button, { mode: "ghost", tone: "default", size: 1, padding: 2, style: { height: "24px", position: "absolute", right: "16px", bottom: "16px", fontSize: "12px" }, text: t("action.update"), onClick: (e) => { e.stopPropagation(), handleUpdate(q_4); } }) ] }) }, q_4._key); }), $[27] = currentParams, $[28] = currentQuery, $[29] = deleteQuery, $[30] = editingKey, $[31] = editingTitle, $[32] = formatDate, $[33] = getStateFromUrl, $[34] = handleSave, $[35] = handleTitleSave, $[36] = handleUpdate, $[37] = optimisticTitles, $[38] = queries, $[39] = saving, $[40] = searchQuery, $[41] = selectedUrl, $[42] = setStateFromParsedUrl, $[43] = t, $[44] = T0, $[45] = T1, $[46] = t6, $[47] = t7, $[48] = t8; } else T0 = $[44], T1 = $[45], t6 = $[46], t7 = $[47], t8 = $[48]; let t9; $[72] !== T0 || $[73] !== t6 || $[74] !== t7 ? (t9 = /* @__PURE__ */ jsx(T0, { paddingY: t6, children: t7 }), $[72] = T0, $[73] = t6, $[74] = t7, $[75] = t9) : t9 = $[75]; let t10; return $[76] !== T1 || $[77] !== t8 || $[78] !== t9 ? (t10 = /* @__PURE__ */ jsxs(T1, { children: [ t8, t9 ] }), $[76] = T1, $[77] = t8, $[78] = t9, $[79] = t10) : t10 = $[79], t10; } 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(6), { visionRootRef } = t0, [isNarrowBreakpoint, setIsNarrowBreakpoint] = useState(_temp$4), [paneSizeOptions, setPaneSizeOptions] = useState(_temp2$3); let t1, t2; $[0] !== visionRootRef ? (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(); }; }, t2 = [visionRootRef], $[0] = visionRootRef, $[1] = t1, $[2] = t2) : (t1 = $[1], t2 = $[2]), useEffect(t1, t2); let t3; return $[3] !== isNarrowBreakpoint || $[4] !== paneSizeOptions ? (t3 = { paneSizeOptions, isNarrowBreakpoint }, $[3] = isNarrowBreakpoint, $[4] = paneSizeOptions, $[5] = t3) : t3 = $[5], t3; } function _temp2$3() { return calculatePaneSizeOptions(void 0); } function _temp$4() { 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] === /* @__PURE__ */ 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] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = () => setOpen(_temp$3), $[0] = t0) : t0 = $[0]; const handleClick = t0, { t } = useTranslation(visionLocaleNamespace); let t1, t2; $[1] === /* @__PURE__ */ 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://www.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] === /* @__PURE__ */ 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$3(o) { return !o; } const PinnedReleasePerspectiveOption = (t0) => { const $ = c(11), { 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; $[3] !== label || $[4] !== name ? (t2 = [name, label].filter(_temp$2), $[3] = label, $[4] = name, $[5] = t2) : t2 = $[5]; const text = t2.join(" "); let t3; $[6] !== pinnedPerspective ? (t3 = hasPinnedPerspective(pinnedPerspective), $[6] = pinnedPerspective, $[7] = t3) : t3 = $[7]; const t4 = !t3; let t5; return $[8] !== t4 || $[9] !== text ? (t5 = /* @__PURE__ */ jsx("option", { value: "pinnedRelease", disabled: t4, children: text }), $[8] = t4, $[9] = text, $[10] = t5) : t5 = $[10], t5; }; function VisionGuiHeader(t0) { const $ = c(65), { onChangeDataset, dataset, customApiVersion, apiVersion, onChangeApiVersion, datasets, customApiVersionElementRef, onCustomApiVersionChange, isValidApiVersion, onChangePerspective, url, perspective, isScheduledDraftsEnabled } = t0, pinnedPerspective = usePerspective(), { t } = useTranslation(visionLocaleNamespace), operationUrlElement = useRef(null); let t1; $[0] === /* @__PURE__ */ 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] === /* @__PURE__ */ 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$2), $[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] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t11 = API_VERSIONS.map(_temp3$1), $[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] === /* @__PURE__ */ 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] !== isScheduledDraftsEnabled || $[45] !== pinnedPerspective || $[46] !== 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") : perspectiveName === "scheduledDrafts" ? isScheduledDraftsEnabled ? /* @__PURE__ */ jsx("option", { value: "scheduledDrafts", children: t("settings.perspectives.scheduled-drafts") }, "scheduledDrafts") : null : /* @__PURE__ */ jsx("option", { children: perspectiveName }, perspectiveName)), $[44] = isScheduledDraftsEnabled, $[45] = pinnedPerspective, $[46] = t, $[47] = t22) : t22 = $[47]; let t23; $[48] !== onChangePerspective || $[49] !== t21 || $[50] !== t22 ? (t23 = /* @__PURE__ */ jsx(Select, { value: t21, onChange: onChangePerspective, children: t22 }), $[48] = onChangePerspective, $[49] = t21, $[50] = t22, $[51] = t23) : t23 = $[51]; let t24; $[52] !== t20 || $[53] !== t23 ? (t24 = /* @__PURE__ */ jsx(Box, { padding: 1, column: 2, children: /* @__PURE__ */ jsxs(Stack, { children: [ t20, t23 ] }) }), $[52] = t20, $[53] = t23, $[54] = t24) : t24 = $[54]; let t25; $[55] !== customApiVersion || $[56] !== t || $[57] !== 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: