UNPKG

@sanity/vision

Version:

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

1,076 lines (1,074 loc) • 123 kB
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime"; import { c } from "react/compiler-runtime"; import { useTranslation, useKeyValueStore, useClient, useCurrentUser, useDateTimeFormat, ContextMenuButton, UserAvatar, Translate, usePerspective, useDataset, useScheduledDraftsEnabled, useActiveReleases, useWorkspace, sortReleases, isCardinalityOneRelease, getReleaseIdFromReleaseDocumentId } from "sanity"; import { Spinner, rem, useTheme, Flex, Box, Label, Card, useTheme_v2, Text, Tooltip, useToast, Stack, TextInput, MenuButton, Menu, MenuItem, Code, Badge, Button, Dialog, Tab, TabList, Hotkeys, useClickOutsideEvent, Popover, Inline, 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 { ChevronLeftIcon } from "@sanity/icons/ChevronLeft"; import { ChevronRightIcon } from "@sanity/icons/ChevronRight"; import { isHotkey } from "is-hotkey-esm"; 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 { groq } from "@sanity/lezer-groq"; import CodeMirror, { EditorSelection } from "@uiw/react-codemirror"; import { assignInlineVars } from "@vanilla-extract/dynamic"; import { tags } from "@lezer/highlight"; import { hues } from "@sanity/color"; import { visionLocaleNamespace } from "./index.js"; import { ErrorOutlineIcon } from "@sanity/icons/ErrorOutline"; import debounce from "lodash-es/debounce.js"; import JSON5 from "json5"; import { AddIcon } from "@sanity/icons/Add"; import { LockIcon } from "@sanity/icons/Lock"; import { SearchIcon } from "@sanity/icons/Search"; import { TrashIcon } from "@sanity/icons/Trash"; import { UnpublishIcon } from "@sanity/icons/Unpublish"; import { UsersIcon } from "@sanity/icons/Users"; import isEqual from "lodash-es/isEqual.js"; import { uuid } from "@sanity/uuid"; import { startWith, map } from "rxjs/operators"; import { PlayIcon } from "@sanity/icons/Play"; import { StopIcon } from "@sanity/icons/Stop"; import { CopyIcon } from "@sanity/icons/Copy"; import { HelpCircleIcon } from "@sanity/icons/HelpCircle"; import { json2csv } from "json-2-csv"; import { JsonInspector } from "@rexxars/react-json-inspector"; import { LinkIcon } from "@sanity/icons/Link"; import LRU from "quick-lru"; import { IntentLink } from "sanity/router"; import { DocumentSheetIcon } from "@sanity/icons/DocumentSheet"; 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 sharedExtensions = [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))], groqExtensions = [groq(), ...sharedExtensions], paramsExtensions = [javascriptLanguage, ...sharedExtensions]; 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 }]); } var contentBorderRightWidthVar = "var(--_116kdfx1)", contentPaddingTopVar = "var(--_116kdfx2)", editorRoot = "_116kdfx3", linePaddingLeftVar = "var(--_116kdfx0)"; function EditorRoot(t0) { const $ = c(13), { children } = t0, { sanity } = useTheme(); let t1; $[0] !== sanity.space[3] ? (t1 = rem(sanity.space[3]), $[0] = sanity.space[3], $[1] = t1) : t1 = $[1]; const t2 = `${t1}`; let t3; $[2] !== sanity.space[4] ? (t3 = rem(sanity.space[4]), $[2] = sanity.space[4], $[3] = t3) : t3 = $[3]; const t4 = `${t3}`; let t5; $[4] !== sanity.space[5] ? (t5 = rem(sanity.space[5]), $[4] = sanity.space[5], $[5] = t5) : t5 = $[5]; const t6 = `${t5}`; let t7; $[6] !== t2 || $[7] !== t4 || $[8] !== t6 ? (t7 = assignInlineVars({ [linePaddingLeftVar]: t2, [contentBorderRightWidthVar]: t4, [contentPaddingTopVar]: t6 }), $[6] = t2, $[7] = t4, $[8] = t6, $[9] = t7) : t7 = $[9]; let t8; return $[10] !== children || $[11] !== t7 ? (t8 = /* @__PURE__ */ jsx("div", { className: editorRoot, style: t7, children }), $[10] = children, $[11] = t7, $[12] = t8) : t8 = $[12], t8; } const VisionCodeMirror = forwardRef((props, ref) => { const $ = c(8), [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.extensions || $[5] !== props.onChange || $[6] !== theme ? (t3 = /* @__PURE__ */ jsx(EditorRoot, { children: /* @__PURE__ */ jsx(CodeMirror, { ref: codeMirrorRef, basicSetup: !1, theme, extensions: props.extensions, value: initialValue, onChange: props.onChange }) }), $[3] = initialValue, $[4] = props.extensions, $[5] = props.onChange, $[6] = theme, $[7] = t3) : t3 = $[7], 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; } } var controlsContainer = "ior2o0k", downloadsCard = "ior2o0h", header = "ior2o01", inputBackgroundContainer = "ior2o05", inputBackgroundContainerLeft = "ior2o06", inputContainer = "ior2o07", queryCopyLink = "ior2o04", result = "ior2o0c", resultContainer = "ior2o0a", resultContainerInvalid = "ior2o0b", resultFooter = "ior2o0d", resultInnerContainer = "ior2o09", resultOuterContainer = "ior2o08", root = "ior2o00", saveResultLabel = "ior2o0j", saveResultSpanGapVar = "var(--ior2o0i)", splitpaneContainer = "ior2o03", styledLabel = "ior2o02", timingsCard = "ior2o0e", timingsTextContainer = "ior2o0g", timingsTextMinHeightVar = "var(--ior2o0f)"; const Root = forwardRef(function(props, ref) { const $ = c(3); let t0; return $[0] !== props || $[1] !== ref ? (t0 = /* @__PURE__ */ jsx(Flex, { ...props, ref, className: root }), $[0] = props, $[1] = ref, $[2] = t0) : t0 = $[2], t0; }); function Header(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Card, { ...props, className: header }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function StyledLabel(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Label, { ...props, className: styledLabel }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function SplitpaneContainer(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Box, { ...props, className: splitpaneContainer }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function QueryCopyLink(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx("a", { ...props, className: queryCopyLink }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function InputBackgroundContainer(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Box, { ...props, className: inputBackgroundContainer }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function InputBackgroundContainerLeft(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Box, { ...props, className: `${inputBackgroundContainer} ${inputBackgroundContainerLeft}` }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function InputContainer(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Card, { ...props, className: inputContainer }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function ResultOuterContainer(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Flex, { ...props, className: resultOuterContainer }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function ResultInnerContainer(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Box, { ...props, className: resultInnerContainer }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function ResultContainer(t0) { const $ = c(6); let isInvalid, props; $[0] !== t0 ? ({ isInvalid, ...props } = t0, $[0] = t0, $[1] = isInvalid, $[2] = props) : (isInvalid = $[1], props = $[2]); const t1 = isInvalid ? `${resultContainer} ${resultContainerInvalid}` : resultContainer; let t2; return $[3] !== props || $[4] !== t1 ? (t2 = /* @__PURE__ */ jsx(Card, { ...props, className: t1 }), $[3] = props, $[4] = t1, $[5] = t2) : t2 = $[5], t2; } function Result(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Box, { ...props, className: result }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function ResultFooter(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Flex, { ...props, className: resultFooter }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function TimingsCard(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Card, { ...props, className: timingsCard }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function TimingsTextContainer(props) { const $ = c(7), { space, font } = useTheme_v2(), textSize = font.text.sizes[2], t0 = space[3] * 2 + textSize.lineHeight - textSize.ascenderHeight - textSize.descenderHeight; let t1; $[0] !== t0 ? (t1 = rem(t0), $[0] = t0, $[1] = t1) : t1 = $[1]; const t2 = `${t1}`; let t3; $[2] !== t2 ? (t3 = assignInlineVars({ [timingsTextMinHeightVar]: t2 }), $[2] = t2, $[3] = t3) : t3 = $[3]; let t4; return $[4] !== props || $[5] !== t3 ? (t4 = /* @__PURE__ */ jsx(Flex, { ...props, className: timingsTextContainer, style: t3 }), $[4] = props, $[5] = t3, $[6] = t4) : t4 = $[6], t4; } function DownloadsCard(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Card, { ...props, className: downloadsCard }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function SaveResultLabel(props) { const $ = c(7), { space } = useTheme_v2(); let t0; $[0] !== space[3] ? (t0 = rem(space[3]), $[0] = space[3], $[1] = t0) : t0 = $[1]; const t1 = `${t0}`; let t2; $[2] !== t1 ? (t2 = assignInlineVars({ [saveResultSpanGapVar]: t1 }), $[2] = t1, $[3] = t2) : t2 = $[3]; let t3; return $[4] !== props || $[5] !== t2 ? (t3 = /* @__PURE__ */ jsx(Text, { ...props, className: saveResultLabel, style: t2 }), $[4] = props, $[5] = t2, $[6] = t3) : t3 = $[6], t3; } function ControlsContainer(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Box, { ...props, className: controlsContainer }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } const 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, extensions: paramsExtensions }), $[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", SHARED_QUERY_DOCUMENT_TYPE = "vision.sharedQuery", SHARED_QUERIES_QUERY = `*[_type == $sharedQueryType]{ _id, authorId, savedAt, title, url } | order(savedAt desc)`, SHARED_QUERY_LISTEN_OPTIONS = { events: ["welcome", "mutation", "reconnect"], includeResult: !0, visibility: "query" }, defaultValue = { queries: [] }, keyValueStoreKey = STORED_QUERIES_NAMESPACE; function useSavedQueries() { const $ = c(45), keyValueStore = useKeyValueStore(); let t0; $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = { apiVersion: DEFAULT_API_VERSION }, $[0] = t0) : t0 = $[0]; const workspaceClient = useClient(t0), currentUser = useCurrentUser(), [value, setValue] = useState(defaultValue); let t1; $[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = [], $[1] = t1) : t1 = $[1]; const [sharedQueries, setSharedQueries] = useState(t1), [saving, setSaving] = useState(!1); let t2; $[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t2 = [], $[2] = t2) : t2 = $[2]; const [deleting, setDeleting] = useState(t2), [saveQueryError, setSaveQueryError] = useState(), [deleteQueryError, setDeleteQueryError] = useState(), [error, setError] = useState(); let t3; $[3] !== keyValueStore ? (t3 = keyValueStore.getKey(keyValueStoreKey), $[3] = keyValueStore, $[4] = t3) : t3 = $[4]; const personalQueries = t3; let t4; $[5] !== currentUser?.id ? (t4 = (docs) => { const currentUserId = currentUser?.id; return docs.map((doc) => ({ _key: doc._id, authorId: doc.authorId, isOwnedByCurrentUser: doc.authorId === currentUserId, savedAt: doc.savedAt, shared: !0, title: doc.title, url: doc.url })); }, $[5] = currentUser?.id, $[6] = t4) : t4 = $[6]; const mapSharedQueries = t4; let t5, t6; $[7] !== personalQueries ? (t5 = () => { const sub = personalQueries.pipe(startWith(defaultValue), map(_temp$5)).subscribe({ next: setValue, error: (err) => setError(err) }); return () => sub?.unsubscribe(); }, t6 = [personalQueries], $[7] = personalQueries, $[8] = t5, $[9] = t6) : (t5 = $[8], t6 = $[9]), useEffect(t5, t6); let t7, t8; $[10] !== mapSharedQueries || $[11] !== workspaceClient ? (t7 = () => { let cancelled = !1; const fetchSharedQueries = async () => { const nextDocs = await workspaceClient.fetch(SHARED_QUERIES_QUERY, { sharedQueryType: SHARED_QUERY_DOCUMENT_TYPE }) || []; cancelled || setSharedQueries(mapSharedQueries(nextDocs)); }; fetchSharedQueries().catch((err_0) => { cancelled || setError(err_0); }); const sub_0 = workspaceClient.observable.listen("*[_type == $sharedQueryType]", { sharedQueryType: SHARED_QUERY_DOCUMENT_TYPE }, SHARED_QUERY_LISTEN_OPTIONS).subscribe({ next: () => { fetchSharedQueries().catch((err_1) => { cancelled || setError(err_1); }); }, error: (err_2) => { cancelled || setError(err_2); } }); return () => { cancelled = !0, sub_0.unsubscribe(); }; }, t8 = [workspaceClient, mapSharedQueries], $[10] = mapSharedQueries, $[11] = workspaceClient, $[12] = t7, $[13] = t8) : (t7 = $[12], t8 = $[13]), useEffect(t7, t8); let t9; $[14] !== sharedQueries || $[15] !== value.queries ? (t9 = [...sharedQueries, ...value.queries].sort(_temp2$4), $[14] = sharedQueries, $[15] = value.queries, $[16] = t9) : t9 = $[16]; const queries = t9; let t10; $[17] !== currentUser || $[18] !== keyValueStore || $[19] !== mapSharedQueries || $[20] !== value.queries || $[21] !== workspaceClient ? (t10 = async (query) => { if (setSaving(!0), setSaveQueryError(void 0), query.shared) { if (!currentUser?.id) { const authError = new Error("No current user found. Unable to save shared query."); throw setSaveQueryError(authError), setSaving(!1), authError; } try { const createdDoc = await workspaceClient.create({ _type: SHARED_QUERY_DOCUMENT_TYPE, authorId: currentUser.id, savedAt: query.savedAt, title: query.title, url: query.url }); setSharedQueries((prev) => [...mapSharedQueries([createdDoc]), ...prev]), setSaving(!1); return; } catch (t112) { const err_3 = t112, saveError = err_3 instanceof Error ? err_3 : new Error(String(err_3)); throw setSaveQueryError(saveError), setSaving(!1), saveError; } } try { const newQueries = [{ ...query, _key: uuid() }, ...value.queries]; setValue({ queries: newQueries }), await keyValueStore.setKey(keyValueStoreKey, { queries: newQueries }); } catch (t122) { const err_4 = t122, saveError_0 = err_4 instanceof Error ? err_4 : new Error(String(err_4)); throw setSaveQueryError(saveError_0), setSaving(!1), saveError_0; } setSaving(!1); }, $[17] = currentUser, $[18] = keyValueStore, $[19] = mapSharedQueries, $[20] = value.queries, $[21] = workspaceClient, $[22] = t10) : t10 = $[22]; const saveQuery = t10; let t11; $[23] !== currentUser || $[24] !== keyValueStore || $[25] !== mapSharedQueries || $[26] !== value.queries || $[27] !== workspaceClient ? (t11 = async (query_0) => { if (setSaving(!0), setSaveQueryError(void 0), query_0.shared) { if (!currentUser?.id || query_0.authorId !== currentUser.id) { const authError_0 = new Error("Only the author can update a shared query."); throw setSaveQueryError(authError_0), setSaving(!1), authError_0; } try { const updatedDoc = await workspaceClient.patch(query_0._key).set({ savedAt: query_0.savedAt, title: query_0.title, url: query_0.url }).commit(), [updatedSharedQuery] = mapSharedQueries([updatedDoc]); setSharedQueries((prev_0) => prev_0.map((existingQuery) => existingQuery._key === query_0._key ? updatedSharedQuery : existingQuery)), setSaving(!1); return; } catch (t122) { const err_5 = t122, updateError = err_5 instanceof Error ? err_5 : new Error(String(err_5)); throw setSaveQueryError(updateError), setSaving(!1), updateError; } } 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 (t132) { const err_6 = t132, updateError_0 = err_6 instanceof Error ? err_6 : new Error(String(err_6)); throw setSaveQueryError(updateError_0), setSaving(!1), updateError_0; } setSaving(!1); }, $[23] = currentUser, $[24] = keyValueStore, $[25] = mapSharedQueries, $[26] = value.queries, $[27] = workspaceClient, $[28] = t11) : t11 = $[28]; const updateQuery = t11; let t12; $[29] !== currentUser || $[30] !== keyValueStore || $[31] !== sharedQueries || $[32] !== value.queries || $[33] !== workspaceClient ? (t12 = async (key) => { setDeleting((prev_1) => [...prev_1, key]), setDeleteQueryError(void 0); const clearDeleting = () => setDeleting((prev_2) => prev_2.filter((k) => k !== key)), sharedQuery = sharedQueries.find((query_1) => query_1._key === key && query_1.shared); if (sharedQuery) { if (!currentUser?.id || sharedQuery.authorId !== currentUser.id) { setDeleteQueryError(new Error("Only the author can delete a shared query.")), clearDeleting(); return; } try { await workspaceClient.delete(key), setSharedQueries((prev_3) => prev_3.filter((query_2) => query_2._key !== key)); } catch (t132) { setDeleteQueryError(t132); } clearDeleting(); return; } try { const filteredQueries = value.queries.filter((q_0) => q_0._key !== key); setValue({ queries: filteredQueries }), await keyValueStore.setKey(keyValueStoreKey, { queries: filteredQueries }); } catch (t14) { setDeleteQueryError(t14); } clearDeleting(); }, $[29] = currentUser, $[30] = keyValueStore, $[31] = sharedQueries, $[32] = value.queries, $[33] = workspaceClient, $[34] = t12) : t12 = $[34]; const deleteQuery = t12; let t13; return $[35] !== deleteQuery || $[36] !== deleteQueryError || $[37] !== deleting || $[38] !== error || $[39] !== queries || $[40] !== saveQuery || $[41] !== saveQueryError || $[42] !== saving || $[43] !== updateQuery ? (t13 = { queries, saveQuery, updateQuery, deleteQuery, saving, deleting, saveQueryError, deleteQueryError, error }, $[35] = deleteQuery, $[36] = deleteQueryError, $[37] = deleting, $[38] = error, $[39] = queries, $[40] = saveQuery, $[41] = saveQueryError, $[42] = saving, $[43] = updateQuery, $[44] = t13) : t13 = $[44], t13; } function _temp2$4(a, b) { return new Date(b.savedAt || 0).getTime() - new Date(a.savedAt || 0).getTime(); } function _temp$5(data) { return data || defaultValue; } var fixedHeader = "_15lckbo0", scrollContainer = "_15lckbo1"; function FixedHeader(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Stack, { ...props, className: fixedHeader }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function ScrollContainer(props) { const $ = c(2); let t0; return $[0] !== props ? (t0 = /* @__PURE__ */ jsx(Box, { ...props, className: scrollContainer }), $[0] = props, $[1] = t0) : t0 = $[1], t0; } function QueryRecall(t0) { const $ = c(130), { url, getStateFromUrl, setStateFromParsedUrl, currentQuery, currentParams, generateUrl, compactMode: t1 } = t0, compactMode = t1 === void 0 ? !1 : t1, toast = useToast(), { saveQuery, updateQuery, queries, deleteQuery, saving } = useSavedQueries(), { t } = useTranslation(visionLocaleNamespace); let t2; $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t2 = { month: "short", day: "numeric", year: "numeric", hour: "numeric", minute: "2-digit", hour12: !0 }, $[0] = t2) : t2 = $[0]; const formatDate = useDateTimeFormat(t2), [editingKey, setEditingKey] = useState(null), [editingTitle, setEditingTitle] = useState(""); let t3; $[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t3 = {}, $[1] = t3) : t3 = $[1]; const [optimisticTitles, setOptimisticTitles] = useState(t3), [searchQuery, setSearchQuery] = useState(""), [queryFilter, setQueryFilter] = useState("all"), [selectedUrl, setSelectedUrl] = useState(url); let t4; $[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t4 = [], $[2] = t4) : t4 = $[2]; const [pendingUnshareKeys, setPendingUnshareKeys] = useState(t4), [shareDialogQuery, setShareDialogQuery] = useState(null); let t5; $[3] !== currentParams || $[4] !== currentQuery || $[5] !== formatDate || $[6] !== generateUrl || $[7] !== getStateFromUrl || $[8] !== queries || $[9] !== saveQuery || $[10] !== t || $[11] !== toast ? (t5 = async () => { const newUrl = generateUrl(currentQuery, currentParams); if (queries?.some((q) => { if (q.shared) return !1; const savedQueryObj = getStateFromUrl(q.url); return savedQueryObj && savedQueryObj.query === currentQuery && isEqual(savedQueryObj.params, currentParams); })) { const duplicateQuery = queries?.find((q_0) => { if (q_0.shared) return !1; 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; } if (newUrl) try { await saveQuery({ shared: !1, url: newUrl, savedAt: (/* @__PURE__ */ new Date()).toISOString(), title: t("label.untitled-query") }), setSelectedUrl(newUrl), toast.push({ closable: !0, status: "success", title: t("save-query.success") }); } catch (t62) { const err = t62; toast.push({ closable: !0, status: "error", title: t("save-query.error"), description: err instanceof Error ? err.message : String(err) }); } }, $[3] = currentParams, $[4] = currentQuery, $[5] = formatDate, $[6] = generateUrl, $[7] = getStateFromUrl, $[8] = queries, $[9] = saveQuery, $[10] = t, $[11] = toast, $[12] = t5) : t5 = $[12]; const handleSave = t5; let t6; $[13] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t6 = (query) => { setShareDialogQuery(query); }, $[13] = t6) : t6 = $[13]; const handleShareQuery = t6; let t7; $[14] !== deleteQuery || $[15] !== saveQuery || $[16] !== shareDialogQuery || $[17] !== t || $[18] !== toast ? (t7 = async () => { if (!shareDialogQuery) return; const sharedQueryKey = shareDialogQuery._key, sharedQueryUrl = shareDialogQuery.url, sharedQueryTitle = shareDialogQuery.title || t("label.untitled-query"); try { await saveQuery({ shared: !0, title: sharedQueryTitle, url: sharedQueryUrl, savedAt: (/* @__PURE__ */ new Date()).toISOString() }), await deleteQuery(sharedQueryKey), toast.push({ closable: !0, status: "success", title: t("save-query.shared-success") }); } catch (t82) { const err_0 = t82; toast.push({ closable: !0, status: "error", title: t("save-query.error"), description: err_0 instanceof Error ? err_0.message : String(err_0) }); } setShareDialogQuery(null); }, $[14] = deleteQuery, $[15] = saveQuery, $[16] = shareDialogQuery, $[17] = t, $[18] = toast, $[19] = t7) : t7 = $[19]; const handleConfirmShareQuery = t7; let t8; $[20] !== deleteQuery || $[21] !== formatDate || $[22] !== getStateFromUrl || $[23] !== queries || $[24] !== saveQuery || $[25] !== t || $[26] !== toast ? (t8 = async (query_0) => { setPendingUnshareKeys((prev) => [...prev, query_0._key]); const clearPending = () => setPendingUnshareKeys((prev_0) => prev_0.filter((key) => key !== query_0._key)), nextQueryObj = getStateFromUrl(query_0.url), duplicatePersonalQuery = queries?.find((existingQuery) => { if (existingQuery._key === query_0._key || existingQuery.shared) return !1; const existingQueryObj = getStateFromUrl(existingQuery.url); return nextQueryObj && existingQueryObj && existingQueryObj.query === nextQueryObj.query && isEqual(existingQueryObj.params, nextQueryObj.params); }), unsharedQueryTitle = query_0.title || t("label.untitled-query"); if (duplicatePersonalQuery) { toast.push({ closable: !0, status: "warning", title: t("save-query.already-saved"), description: `${duplicatePersonalQuery.title} - ${formatDate.format(new Date(duplicatePersonalQuery.savedAt || ""))}` }), clearPending(); return; } try { await saveQuery({ shared: !1, title: unsharedQueryTitle, url: query_0.url, savedAt: (/* @__PURE__ */ new Date()).toISOString() }), await deleteQuery(query_0._key), toast.push({ closable: !0, status: "success", title: t("save-query.unshared-success") }), clearPending(); } catch (t92) { const err_1 = t92; toast.push({ closable: !0, status: "error", title: t("save-query.error"), description: err_1 instanceof Error ? err_1.message : String(err_1) }), clearPending(); } }, $[20] = deleteQuery, $[21] = formatDate, $[22] = getStateFromUrl, $[23] = queries, $[24] = saveQuery, $[25] = t, $[26] = toast, $[27] = t8) : t8 = $[27]; const handleUnshareQuery = t8; let t9; $[28] !== t || $[29] !== toast || $[30] !== updateQuery ? (t9 = async (query_1, newTitle) => { setEditingKey(null), setOptimisticTitles((prev_1) => ({ ...prev_1, [query_1._key]: newTitle })); try { await updateQuery({ ...query_1, title: newTitle }), setOptimisticTitles((prev_3) => { const next_0 = { ...prev_3 }; return delete next_0[query_1._key], next_0; }); } catch (t102) { const err_2 = t102; setOptimisticTitles((prev_2) => { const next = { ...prev_2 }; return delete next[query_1._key], next; }), toast.push({ closable: !0, status: "error", title: t("save-query.error"), description: err_2.message }); } }, $[28] = t, $[29] = toast, $[30] = updateQuery, $[31] = t9) : t9 = $[31]; const handleTitleSave = t9; let t10; $[32] !== currentParams || $[33] !== currentQuery || $[34] !== formatDate || $[35] !== generateUrl || $[36] !== getStateFromUrl || $[37] !== queries || $[38] !== t || $[39] !== toast || $[40] !== updateQuery ? (t10 = async (query_2) => { const newUrl_0 = generateUrl(currentQuery, currentParams); if (queries?.some((q_1) => { if (q_1._key === query_2._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_2._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_2, url: newUrl_0, savedAt: (/* @__PURE__ */ new Date()).toISOString() }), setSelectedUrl(newUrl_0), toast.push({ closable: !0, status: "success", title: t("save-query.success") }); } catch (t112) { const err_3 = t112; toast.push({ closable: !0, status: "error", title: t("save-query.error"), description: err_3.message }); } }, $[32] = currentParams, $[33] = currentQuery, $[34] = formatDate, $[35] = generateUrl, $[36] = getStateFromUrl, $[37] = queries, $[38] = t, $[39] = toast, $[40] = updateQuery, $[41] = t10) : t10 = $[41]; const handleUpdate = t10; let T0, T1, t11, t12, t13, t14; if ($[42] !== compactMode || $[43] !== currentParams || $[44] !== currentQuery || $[45] !== deleteQuery || $[46] !== editingKey || $[47] !== editingTitle || $[48] !== formatDate || $[49] !== getStateFromUrl || $[50] !== handleSave || $[51] !== handleTitleSave || $[52] !== handleUnshareQuery || $[53] !== handleUpdate || $[54] !== optimisticTitles || $[55] !== pendingUnshareKeys || $[56] !== queries || $[57] !== queryFilter || $[58] !== saving || $[59] !== searchQuery || $[60] !== selectedUrl || $[61] !== setStateFromParsedUrl || $[62] !== t) { const filteredQueries = queries?.filter((q_3) => !pendingUnshareKeys.includes(q_3._key))?.filter((q_4) => { const matchesSearch = (q_4.title ?? "").toLowerCase().includes(searchQuery.toLowerCase()), matchesFilter = queryFilter === "all" || queryFilter === "personal" && !q_4.shared || queryFilter === "shared" && q_4.shared; return matchesSearch && matchesFilter; }); T1 = ScrollContainer; let t152; $[69] !== t ? (t152 = t("label.saved-queries"), $[69] = t, $[70] = t152) : t152 = $[70]; let t162; $[71] !== t152 ? (t162 = /* @__PURE__ */ jsx(StyledLabel, { muted: !0, children: t152 }), $[71] = t152, $[72] = t162) : t162 = $[72]; let t172; $[73] !== t ? (t172 = t("action.save-query"), $[73] = t, $[74] = t172) : t172 = $[74]; let t18; $[75] !== handleSave ? (t18 = () => { handleSave(); }, $[75] = handleSave, $[76] = t18) : t18 = $[76]; let t19; $[77] !== saving || $[78] !== t172 || $[79] !== t18 ? (t19 = /* @__PURE__ */ jsx(Button, { "aria-label": t172, icon: AddIcon, disabled: saving, onClick: t18, mode: "bleed" }), $[77] = saving, $[78] = t172, $[79] = t18, $[80] = t19) : t19 = $[80]; let t20; $[81] !== t162 || $[82] !== t19 ? (t20 = /* @__PURE__ */ jsxs(Flex, { padding: 3, paddingTop: 2, paddingBottom: 0, justify: "space-between", align: "center", children: [ t162, t19 ] }), $[81] = t162, $[82] = t19, $[83] = t20) : t20 = $[83]; let t21; $[84] !== t ? (t21 = t("label.search-queries"), $[84] = t, $[85] = t21) : t21 = $[85]; let t22; $[86] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t22 = (event) => setSearchQuery(event.currentTarget.value), $[86] = t22) : t22 = $[86]; let t23; $[87] !== searchQuery || $[88] !== t21 ? (t23 = /* @__PURE__ */ jsx(Box, { padding: 3, paddingTop: 0, children: /* @__PURE__ */ jsx(TextInput, { placeholder: t21, icon: SearchIcon, value: searchQuery, onChange: t22 }) }), $[87] = searchQuery, $[88] = t21, $[89] = t23) : t23 = $[89]; let t24; $[90] !== t ? (t24 = t("label.all"), $[90] = t, $[91] = t24) : t24 = $[91]; const t25 = queryFilter === "all"; let t26; $[92] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t26 = () => setQueryFilter("all"), $[92] = t26) : t26 = $[92]; let t27; $[93] !== t24 || $[94] !== t25 ? (t27 = /* @__PURE__ */ jsx(Tab, { id: "query-filter-all", "aria-controls": "vision-query-recall-list", label: t24, selected: t25, onClick: t26 }), $[93] = t24, $[94] = t25, $[95] = t27) : t27 = $[95]; let t28; $[96] !== t ? (t28 = t("label.personal"), $[96] = t, $[97] = t28) : t28 = $[97]; const t29 = queryFilter === "personal"; let t30; $[98] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t30 = () => setQueryFilter("personal"), $[98] = t30) : t30 = $[98]; let t31; $[99] !== t28 || $[100] !== t29 ? (t31 = /* @__PURE__ */ jsx(Tab, { id: "query-filter-personal", "aria-controls": "vision-query-recall-list", label: t28, selected: t29, onClick: t30 }), $[99] = t28, $[100] = t29, $[101] = t31) : t31 = $[101]; let t32; $[102] !== t ? (t32 = t("label.shared"), $[102] = t, $[103] = t32) : t32 = $[103]; const t33 = queryFilter === "shared"; let t34; $[104] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t34 = () => setQueryFilter("shared"), $[104] = t34) : t34 = $[104]; let t35; $[105] !== t32 || $[106] !== t33 ? (t35 = /* @__PURE__ */ jsx(Tab, { id: "query-filter-shared", "aria-controls": "vision-query-recall-list", label: t32, selected: t33, onClick: t34 }), $[105] = t32, $[106] = t33, $[107] = t35) : t35 = $[107]; let t36; $[108] !== t27 || $[109] !== t31 || $[110] !== t35 ? (t36 = /* @__PURE__ */ jsx(Box, { paddingX: 3, paddingBottom: 2, children: /* @__PURE__ */ jsxs(TabList, { space: 1, children: [ t27, t31, t35 ] }) }), $[108] = t27, $[109] = t31, $[110] = t35, $[111] = t36) : t36 = $[111], $[112] !== t20 || $[113] !== t23 || $[114] !== t36 ? (t14 = /* @__PURE__ */ jsxs(FixedHeader, { space: 3, children: [ t20, t23, t36 ] }), $[112] = t20, $[113] = t23, $[114] = t36, $[115] = t14) : t14 = $[115], T0 = Stack, t11 = "vision-query-recall-list", t12 = 3, t13 = filteredQueries?.map((q_5, index) => { const queryObj = getStateFromUrl(q_5.url), fullQueryPreview = queryObj?.query || "", shortQueryPreview = fullQueryPreview.split("{")[0], isSelected = selectedUrl === q_5.url, canMutateQuery = !q_5.shared || q_5.isOwnedByCurrentUser, areQueriesEqual = queryObj && currentQuery === queryObj.query && isEqual(currentParams, queryObj.params), isEdited = isSelected && !areQueriesEqual && canMutateQuery; return /* @__PURE__ */ jsx(Card, { paddingX: compactMode ? 3 : 4, paddingY: compactMode ? 3 : 4, tone: "default", onClick: (event_0) => { if (event_0.target?.closest('[data-query-actions="true"]')) return; setSelectedUrl(q_5.url); const parsedUrl = getStateFromUrl(q_5.url); parsedUrl && setStateFromParsedUrl(parsedUrl); }, style: { borderTop: index === 0 ? "1px solid var(--card-border-color)" : void 0, position: "relative", borderBottom: "1px solid var(--card-border-color)", borderLeft: isSelected ? "2px solid var(--card-muted-fg-color)" : "2px solid transparent", cursor: "pointer" }, children: /* @__PURE__ */ jsxs(Stack, { space: compactMode ? 2 : 3, children: [ /* @__PURE__ */ jsxs(Flex, { justify: "space-between", align: "center", style: { minHeight: "25px" }, children: [ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, paddingRight: 1, style: { minWidth: 0, flex: 1 }, children: [ editingKey === q_5._key ? /* @__PURE__ */ jsx(TextInput, { value: editingTitle, onChange: (event_1) => setEditingTitle(event_1.currentTarget.value), onKeyDown: (event_2) => { event_2.key === "Enter" ? handleTitleSave(q_5, editingTitle) : event_2.key === "Escape" && setEditingKey(null); }, onBlur: () => handleTitleSave(q_5, editingTitle), autoFocus: !0, style: { maxWidth: "170px", height: "24px" } }) : /* @__PURE__ */ jsx(Text, { weight: "bold", size: compactMode ? 2 : 3, textOverflow: "ellipsis", style: { maxWidth: compactMode ? "180px" : "220px", cursor: canMutateQuery ? "pointer" : "default", padding: "2px 0" }, title: optimisticTitles[q_5._key] || q_5.title || q_5._key.slice(q_5._key.length - 5, q_5._key.length), onClick: canMutateQuery ? () => { setEditingKey(q_5._key), setEditingTitle(q_5.title || q_5._key.slice(0, 5)); } : void 0, children: optimisticTitles[q_5._key] || q_5.title || q_5._key.slice(q_5._key.length - 5, q_5._key.length) }), isEdited && /* @__PURE__ */ jsx(Box, { style: { width: "6px", height: "6px", borderRadius: "50%", backgroundColor: "var(--card-focus-ring-color)" } }) ] }), /* @__PURE__ */ jsx(Flex, { align: "center", gap: 2, children: /* @__PURE__ */ jsx(Box, { "data-query-actions": "true", style: { width: "25px", height: "25px", display: "flex", alignItems: "center" }, children: (!q_5.shared || canMutateQuery) && /* @__PURE__ */ jsx(MenuButton, { button: /* @__PURE__ */ jsx(ContextMenuButton, {}), id: `${q_5._key}-menu`, menu: /* @__PURE__ */ jsxs(Menu, { children: [ !q_5.shared && /* @__PURE__ */ jsx(MenuItem, { icon: UsersIcon, padding: 3, text: t("label.share"), onClick: (event_3) => { event_3.stopPropagation(), handleShareQuery(q_5); } }), q_5.shared && canMutateQuery && /* @__PURE__ */ jsx(MenuItem, { icon: UnpublishIcon, padding: 3, text: t("action.unshare"), onClick: (event_4) => { event_4.stopPropagation(), handleUnshareQuery(q_5); } }), canMutateQuery && /* @__PURE__ */ jsx(MenuItem, { tone: "critical", padding: 3, icon: TrashIcon, text: t("action.delete"), onClick: (event_5) => { event_5.stopPropagation(), deleteQuery(q_5._key); } }) ] }), popover: { portal: !0, placement: "bottom-end", tone: "default" } }) }) }) ] }), fullQueryPreview ? /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(Box, { padding: 2, style: { maxWidth: "420px", maxHeight: "220px", overflow: "auto" }, children: /* @__PURE__ */ jsx(Code, { size: 1, childr