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