@sanity/embeddings-index-ui 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8,14 +8,61 @@ var jsxRuntime = require('react/jsx-runtime');
8
8
  var ui = require('@sanity/ui');
9
9
  var icons = require('@sanity/icons');
10
10
  var require$$0 = require('react');
11
- var router = require('sanity/router');
12
11
  var desk = require('sanity/desk');
12
+ var router = require('sanity/router');
13
13
  function _interopDefaultCompat(e) {
14
14
  return e && typeof e === 'object' && 'default' in e ? e : {
15
15
  default: e
16
16
  };
17
17
  }
18
18
  var require$$0__default = /*#__PURE__*/_interopDefaultCompat(require$$0);
19
+ function publicId(id) {
20
+ return id.replace("drafts.", "");
21
+ }
22
+ const featureName = "embeddingsIndexApi";
23
+ const FeatureEnabledContext = require$$0.createContext("loading");
24
+ function useIsFeatureEnabled() {
25
+ const client = sanity.useClient({
26
+ apiVersion: "2023-09-01"
27
+ });
28
+ const [status, setStatus] = require$$0.useState("loading");
29
+ require$$0.useEffect(() => {
30
+ client.request({
31
+ method: "GET",
32
+ url: "/projects/".concat(client.config().projectId, "/features/").concat(featureName)
33
+ }).then(isEnabled => {
34
+ setStatus(isEnabled === "true" || isEnabled === true ? "enabled" : "disabled");
35
+ }).catch(err => {
36
+ console.error(err);
37
+ setStatus("disabled");
38
+ });
39
+ }, [client]);
40
+ return status;
41
+ }
42
+ function FeatureEnabledProvider(props) {
43
+ const status = useIsFeatureEnabled();
44
+ return /* @__PURE__ */jsxRuntime.jsx(FeatureEnabledContext.Provider, {
45
+ value: status,
46
+ children: props.children
47
+ });
48
+ }
49
+ function useIsFeatureEnabledContext() {
50
+ return require$$0.useContext(FeatureEnabledContext);
51
+ }
52
+ function FeatureDisabledNotice() {
53
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
54
+ tone: "primary",
55
+ border: true,
56
+ padding: 2,
57
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
58
+ size: 1,
59
+ children: ["Embeddings index APIs are only available on the", " ", /* @__PURE__ */jsxRuntime.jsx("a", {
60
+ href: "https://sanity.io/pricing",
61
+ children: "Team tier and above"
62
+ }), ". Please upgrade to enable access."]
63
+ })
64
+ });
65
+ }
19
66
 
20
67
  /******************************************************************************
21
68
  Copyright (c) Microsoft Corporation.
@@ -1887,9 +1934,6 @@ function deleteIndex(indexName, client) {
1887
1934
  url: "/embeddings-index/".concat(dataset, "/").concat(indexName, "?projectId=").concat(projectId)
1888
1935
  });
1889
1936
  }
1890
- function publicId(id) {
1891
- return id.replace("drafts.", "");
1892
- }
1893
1937
  function useApiClient() {
1894
1938
  const client = sanity.useClient({
1895
1939
  apiVersion: "vX"
@@ -1906,107 +1950,20 @@ function useApiClient() {
1906
1950
  return client;
1907
1951
  }, [client]);
1908
1952
  }
1909
- const featureName = "embeddingsIndexApi";
1910
- const FeatureEnabledContext = require$$0.createContext("loading");
1911
- function useIsFeatureEnabled() {
1912
- const client = sanity.useClient({
1913
- apiVersion: "2023-09-01"
1914
- });
1915
- const [status, setStatus] = require$$0.useState("loading");
1916
- require$$0.useEffect(() => {
1917
- client.request({
1918
- method: "GET",
1919
- url: "/projects/".concat(client.config().projectId, "/features/").concat(featureName)
1920
- }).then(isEnabled => {
1921
- setStatus(isEnabled === "true" || isEnabled === true ? "enabled" : "disabled");
1922
- }).catch(err => {
1923
- console.error(err);
1924
- setStatus("disabled");
1925
- });
1926
- }, [client]);
1927
- return status;
1928
- }
1929
- function FeatureEnabledProvider(props) {
1930
- const status = useIsFeatureEnabled();
1931
- return /* @__PURE__ */jsxRuntime.jsx(FeatureEnabledContext.Provider, {
1932
- value: status,
1933
- children: props.children
1934
- });
1935
- }
1936
- function useIsFeatureEnabledContext() {
1937
- return require$$0.useContext(FeatureEnabledContext);
1938
- }
1939
- function FeatureDisabledNotice() {
1940
- return /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
1941
- tone: "primary",
1942
- border: true,
1943
- padding: 2,
1944
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
1945
- size: 1,
1946
- children: ["Embeddings index APIs are only available on the", " ", /* @__PURE__ */jsxRuntime.jsx("a", {
1947
- href: "https://sanity.io/pricing",
1948
- children: "Team tier and above"
1949
- }), ". Please upgrade to enable access."]
1950
- })
1951
- });
1952
- }
1953
+ const NO_RESULTS_VALUE = "";
1953
1954
  const NO_OPTIONS = [];
1954
1955
  const NO_FILTER = () => true;
1955
- function SemanticSearchReferenceInput(props) {
1956
- var _a, _b, _c;
1957
- const defaultEnabled = ((_c = (_b = (_a = props.schemaType) == null ? void 0 : _a.options) == null ? void 0 : _b.embeddingsIndex) == null ? void 0 : _c.searchMode) === "embeddings";
1958
- const featureState = useIsFeatureEnabledContext();
1959
- const [semantic, setSemantic] = require$$0.useState(defaultEnabled);
1960
- const toggleSemantic = require$$0.useCallback(() => setSemantic(current => !current), []);
1961
- return /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
1962
- gap: 2,
1963
- flex: 1,
1964
- style: {
1965
- width: "100%"
1966
- },
1967
- children: [semantic && featureState == "loading" ? /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1968
- padding: 2,
1969
- children: /* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {})
1970
- }) : null, semantic && featureState == "disabled" ? /* @__PURE__ */jsxRuntime.jsx(FeatureDisabledNotice, {}) : null, /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
1971
- flex: 1,
1972
- style: {
1973
- maxHeight: 36,
1974
- overflow: "hidden"
1975
- },
1976
- children: semantic && featureState == "enabled" ? /* @__PURE__ */jsxRuntime.jsx(SemanticSearchInput, {
1977
- ...props
1978
- }) : props.renderDefault(props)
1979
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
1980
- icon: semantic ? icons.EarthGlobeIcon : icons.LinkIcon,
1981
- onClick: toggleSemantic,
1982
- mode: "bleed",
1983
- title: semantic ? "Switch to standard reference search" : "Switch to semantic reference search"
1984
- })]
1985
- });
1986
- }
1987
- function useDebouncedValue(value, ms) {
1988
- const [debouncedValue, setDebouncedValue] = require$$0.useState(value);
1989
- require$$0.useEffect(() => {
1990
- const timeoutId = setTimeout(() => {
1991
- setDebouncedValue(value);
1992
- }, ms);
1993
- return () => clearTimeout(timeoutId);
1994
- }, [value, ms]);
1995
- return debouncedValue;
1996
- }
1997
- function SemanticSearchInput(props) {
1956
+ const SemanticSearchAutocomplete = require$$0.forwardRef(function SemanticSearchAutocomplete2(props, ref) {
1998
1957
  const {
1999
- onPathFocus,
2000
- onChange,
1958
+ indexConfig,
1959
+ filterResult,
1960
+ getEmptySearchValue,
2001
1961
  readOnly,
2002
- schemaType,
2003
- value
1962
+ onFocus,
1963
+ onBlur,
1964
+ onChange,
1965
+ typeFilter
2004
1966
  } = props;
2005
- const {
2006
- value: currentDocument
2007
- } = desk.useDocumentPane();
2008
- const docRef = require$$0.useRef(currentDocument);
2009
- const autocompleteRef = require$$0.useRef(null);
2010
1967
  const id = require$$0.useId();
2011
1968
  const [query, setQuery] = require$$0.useState("");
2012
1969
  const queryRef = require$$0.useRef(query);
@@ -2015,29 +1972,16 @@ function SemanticSearchInput(props) {
2015
1972
  const [searching, setSearching] = require$$0.useState(false);
2016
1973
  const [options, setOptions] = require$$0.useState(NO_OPTIONS);
2017
1974
  const client = useApiClient();
2018
- require$$0.useEffect(() => {
2019
- docRef.current = currentDocument;
2020
- }, [currentDocument]);
2021
- require$$0.useEffect(() => {
2022
- var _a;
2023
- if (value == null ? void 0 : value._ref) {
2024
- (_a = autocompleteRef.current) == null ? void 0 : _a.focus();
2025
- }
2026
- }, []);
2027
- const handleFocus = require$$0.useCallback(() => onPathFocus(["_ref"]), [onPathFocus]);
2028
- const handleBlur = require$$0.useCallback(() => onPathFocus([]), [onPathFocus]);
2029
1975
  const runIndexQuery = require$$0.useCallback(queryString => {
2030
- var _a, _b, _c, _d, _e;
1976
+ var _a;
2031
1977
  setSearching(true);
2032
- const refSchema = schemaType;
2033
- const indexName = (_b = (_a = refSchema.options) == null ? void 0 : _a.embeddingsIndex) == null ? void 0 : _b.indexName;
2034
- const maxResults = (_d = (_c = refSchema.options) == null ? void 0 : _c.embeddingsIndex) == null ? void 0 : _d.maxResults;
2035
- const typeFilter = refSchema.to.map(ref => ref.name);
1978
+ const indexName = indexConfig == null ? void 0 : indexConfig.indexName;
1979
+ const maxResults = indexConfig == null ? void 0 : indexConfig.maxResults;
2036
1980
  if (!indexName) {
2037
- throw new Error("Reference option embeddingsIndex.indexName is required, but was missing in type ".concat(refSchema.name));
1981
+ throw new Error("Reference option embeddingsIndex.indexName is required, but was missing");
2038
1982
  }
2039
1983
  queryIndex({
2040
- query: queryString.trim().length ? queryString : (_e = JSON.stringify(docRef.current)) != null ? _e : "",
1984
+ query: queryString.trim().length ? queryString : (_a = getEmptySearchValue()) != null ? _a : "",
2041
1985
  indexName,
2042
1986
  maxResults,
2043
1987
  filter: {
@@ -2046,10 +1990,18 @@ function SemanticSearchInput(props) {
2046
1990
  }, client).then(result => {
2047
1991
  if (queryRef.current === queryString) {
2048
1992
  setSearching(false);
2049
- setOptions(result.filter(r => r.value.documentId !== publicId(docRef.current._id)).map(r => sanity.typed({
1993
+ setOptions([]);
1994
+ const resultOptions = result.filter(hit => filterResult ? filterResult(hit) : true).map(r => sanity.typed({
2050
1995
  result: r,
2051
1996
  value: r.value.documentId
2052
- })));
1997
+ }));
1998
+ if (resultOptions.length) {
1999
+ setOptions(resultOptions);
2000
+ } else {
2001
+ setOptions([{
2002
+ value: NO_RESULTS_VALUE
2003
+ }]);
2004
+ }
2053
2005
  }
2054
2006
  }).catch(e => {
2055
2007
  if (queryRef.current === queryString) {
@@ -2057,23 +2009,13 @@ function SemanticSearchInput(props) {
2057
2009
  }
2058
2010
  throw e;
2059
2011
  });
2060
- }, [client, schemaType]);
2012
+ }, [client, indexConfig, getEmptySearchValue, filterResult, typeFilter]);
2061
2013
  require$$0.useEffect(() => {
2062
2014
  if (prevDebouncedQuery.current !== debouncedQuery) {
2063
2015
  runIndexQuery(debouncedQuery);
2064
2016
  }
2065
2017
  prevDebouncedQuery.current = debouncedQuery;
2066
2018
  }, [debouncedQuery, runIndexQuery]);
2067
- const handleChange = require$$0.useCallback(nextId => {
2068
- if (!nextId) {
2069
- onChange(sanity.unset());
2070
- onPathFocus([]);
2071
- return;
2072
- }
2073
- const patches = [sanity.setIfMissing({}), sanity.set(schemaType.name, ["_type"]), sanity.set(publicId(nextId), ["_ref"]), sanity.unset(["_weak"]), sanity.unset(["_strengthenOnPublish"])];
2074
- onChange(patches);
2075
- onPathFocus([]);
2076
- }, [onChange, onPathFocus, schemaType.name]);
2077
2019
  const openButtonConfig = require$$0.useMemo(() => ({
2078
2020
  onClick: () => runIndexQuery(queryRef.current)
2079
2021
  }), [runIndexQuery, queryRef]);
@@ -2082,52 +2024,187 @@ function SemanticSearchInput(props) {
2082
2024
  queryRef.current = newQuery;
2083
2025
  setQuery(newQuery);
2084
2026
  }, [setQuery]);
2027
+ const handleChange = require$$0.useCallback(value => {
2028
+ if (value === NO_RESULTS_VALUE) {
2029
+ setOptions(NO_OPTIONS);
2030
+ return;
2031
+ }
2032
+ onChange == null ? void 0 : onChange(value);
2033
+ }, [onChange]);
2085
2034
  return /* @__PURE__ */jsxRuntime.jsx(ui.Autocomplete, {
2086
2035
  id,
2087
- ref: autocompleteRef,
2036
+ ref,
2088
2037
  "data-testid": "semantic-autocomplete",
2089
2038
  placeholder: "Type to search...",
2090
2039
  openButton: openButtonConfig,
2091
- onFocus: handleFocus,
2040
+ onFocus,
2092
2041
  onChange: handleChange,
2093
2042
  loading: searching,
2094
- onBlur: handleBlur,
2043
+ onBlur,
2095
2044
  readOnly,
2096
2045
  filterOption: NO_FILTER,
2097
2046
  onQueryChange: handleQueryChange,
2098
2047
  options,
2099
2048
  renderOption: AutocompleteOption
2100
2049
  });
2101
- }
2050
+ });
2102
2051
  function AutocompleteOption(props) {
2103
- const value = props.result.value;
2052
+ if ("result" in props) {
2053
+ const value = props.result.value;
2054
+ return /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
2055
+ mode: "bleed",
2056
+ padding: 1,
2057
+ style: {
2058
+ width: "100%"
2059
+ },
2060
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
2061
+ gap: 2,
2062
+ align: "center",
2063
+ children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2064
+ flex: 1,
2065
+ children: /* @__PURE__ */jsxRuntime.jsx(DocumentPreview, {
2066
+ documentId: value.documentId,
2067
+ schemaTypeName: value.type
2068
+ })
2069
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2070
+ padding: 2,
2071
+ children: /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
2072
+ size: 1,
2073
+ muted: true,
2074
+ title: "Relevance",
2075
+ children: [Math.floor(props.result.score * 100), "%"]
2076
+ })
2077
+ })]
2078
+ })
2079
+ });
2080
+ }
2104
2081
  return /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
2105
2082
  mode: "bleed",
2106
2083
  padding: 1,
2107
2084
  style: {
2108
2085
  width: "100%"
2109
2086
  },
2110
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
2087
+ disabled: true,
2088
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
2111
2089
  gap: 2,
2112
2090
  align: "center",
2113
- children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2114
- flex: 1,
2115
- children: /* @__PURE__ */jsxRuntime.jsx(DocumentPreview, {
2116
- documentId: value.documentId,
2117
- schemaTypeName: value.type
2118
- })
2119
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2120
- padding: 2,
2121
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
2122
- size: 1,
2123
- muted: true,
2124
- title: "Relevance",
2125
- children: [Math.floor(props.result.score * 100), "%"]
2126
- })
2127
- })]
2091
+ children: "No results."
2128
2092
  })
2129
2093
  });
2130
2094
  }
2095
+ function useDebouncedValue(value, ms) {
2096
+ const [debouncedValue, setDebouncedValue] = require$$0.useState(value);
2097
+ require$$0.useEffect(() => {
2098
+ const timeoutId = setTimeout(() => {
2099
+ setDebouncedValue(value);
2100
+ }, ms);
2101
+ return () => clearTimeout(timeoutId);
2102
+ }, [value, ms]);
2103
+ return debouncedValue;
2104
+ }
2105
+ function useEmeddingsConfig(embeddingsIndexConfig, defaultConfig) {
2106
+ return require$$0.useMemo(() => {
2107
+ if (embeddingsIndexConfig === true || !embeddingsIndexConfig) {
2108
+ if (!(defaultConfig == null ? void 0 : defaultConfig.indexName)) {
2109
+ throw new Error("Default embeddingsIndex config is missing. When options.embeddingsIndex: true, embeddingsIndexReferenceInput plugin config is required.");
2110
+ }
2111
+ return defaultConfig;
2112
+ }
2113
+ const finalConfig = {
2114
+ ...defaultConfig,
2115
+ ...embeddingsIndexConfig
2116
+ };
2117
+ if (!(finalConfig == null ? void 0 : finalConfig.indexName)) {
2118
+ throw new Error("indexName is missing. Either set it in options.embeddingsIndex or configure defaults using plugin config.");
2119
+ }
2120
+ return finalConfig;
2121
+ }, [defaultConfig, embeddingsIndexConfig]);
2122
+ }
2123
+ function SemanticSearchReferenceInput(props) {
2124
+ var _a, _b;
2125
+ const embeddingsIndexConfig = (_b = (_a = props.schemaType) == null ? void 0 : _a.options) == null ? void 0 : _b.embeddingsIndex;
2126
+ const config = useEmeddingsConfig(embeddingsIndexConfig, props.defaultConfig);
2127
+ const defaultEnabled = config.searchMode === "embeddings";
2128
+ const featureState = useIsFeatureEnabledContext();
2129
+ const [semantic, setSemantic] = require$$0.useState(defaultEnabled);
2130
+ const toggleSemantic = require$$0.useCallback(() => setSemantic(current => !current), []);
2131
+ return /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
2132
+ gap: 2,
2133
+ flex: 1,
2134
+ style: {
2135
+ width: "100%"
2136
+ },
2137
+ children: [semantic && featureState == "loading" ? /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2138
+ padding: 2,
2139
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {})
2140
+ }) : null, semantic && featureState == "disabled" ? /* @__PURE__ */jsxRuntime.jsx(FeatureDisabledNotice, {}) : null, /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2141
+ flex: 1,
2142
+ style: {
2143
+ maxHeight: 36,
2144
+ overflow: "hidden"
2145
+ },
2146
+ children: semantic && featureState == "enabled" ? /* @__PURE__ */jsxRuntime.jsx(SemanticSearchInput, {
2147
+ ...props,
2148
+ indexConfig: config
2149
+ }) : props.renderDefault(props)
2150
+ }), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
2151
+ icon: semantic ? icons.EarthGlobeIcon : icons.LinkIcon,
2152
+ onClick: toggleSemantic,
2153
+ mode: "bleed",
2154
+ title: semantic ? "Switch to standard reference search" : "Switch to semantic reference search"
2155
+ })]
2156
+ });
2157
+ }
2158
+ function SemanticSearchInput(props) {
2159
+ const {
2160
+ indexConfig,
2161
+ onPathFocus,
2162
+ onChange,
2163
+ readOnly,
2164
+ schemaType,
2165
+ value
2166
+ } = props;
2167
+ const {
2168
+ value: currentDocument
2169
+ } = desk.useDocumentPane();
2170
+ const docRef = require$$0.useRef(currentDocument);
2171
+ const autocompleteRef = require$$0.useRef(null);
2172
+ require$$0.useEffect(() => {
2173
+ docRef.current = currentDocument;
2174
+ }, [currentDocument]);
2175
+ require$$0.useEffect(() => {
2176
+ var _a;
2177
+ if (value == null ? void 0 : value._ref) {
2178
+ (_a = autocompleteRef.current) == null ? void 0 : _a.focus();
2179
+ }
2180
+ }, []);
2181
+ const handleFocus = require$$0.useCallback(() => onPathFocus(["_ref"]), [onPathFocus]);
2182
+ const handleBlur = require$$0.useCallback(() => onPathFocus([]), [onPathFocus]);
2183
+ const handleChange = require$$0.useCallback(nextId => {
2184
+ if (!nextId) {
2185
+ onChange(sanity.unset());
2186
+ onPathFocus([]);
2187
+ return;
2188
+ }
2189
+ const patches = [sanity.setIfMissing({}), sanity.set(schemaType.name, ["_type"]), sanity.set(publicId(nextId), ["_ref"]), sanity.unset(["_weak"]), sanity.unset(["_strengthenOnPublish"])];
2190
+ onChange(patches);
2191
+ onPathFocus([]);
2192
+ }, [onChange, onPathFocus, schemaType.name]);
2193
+ const filterResult = require$$0.useCallback(r => r.value.documentId !== publicId(docRef.current._id), [docRef]);
2194
+ const getEmptySearchValue = require$$0.useCallback(() => JSON.stringify(docRef.current), [docRef]);
2195
+ const typeFilter = require$$0.useMemo(() => schemaType.to.map(refType => refType.name), [schemaType]);
2196
+ return /* @__PURE__ */jsxRuntime.jsx(SemanticSearchAutocomplete, {
2197
+ ref: autocompleteRef,
2198
+ typeFilter,
2199
+ indexConfig,
2200
+ onChange: handleChange,
2201
+ onFocus: handleFocus,
2202
+ onBlur: handleBlur,
2203
+ getEmptySearchValue,
2204
+ filterResult,
2205
+ readOnly
2206
+ });
2207
+ }
2131
2208
  function isType(schemaType, typeName) {
2132
2209
  if (schemaType.name === typeName) {
2133
2210
  return true;
@@ -2137,30 +2214,35 @@ function isType(schemaType, typeName) {
2137
2214
  }
2138
2215
  return isType(schemaType.type, typeName);
2139
2216
  }
2140
- const embeddingsIndexReferenceInput = sanity.definePlugin({
2141
- name: "@sanity/embeddings-index-reference-input",
2142
- studio: {
2143
- components: {
2144
- layout: props => {
2145
- return /* @__PURE__ */jsxRuntime.jsx(FeatureEnabledProvider, {
2146
- children: props.renderDefault(props)
2147
- });
2148
- }
2149
- }
2150
- },
2151
- form: {
2152
- components: {
2153
- input: props => {
2154
- var _a, _b;
2155
- if (sanity.isObjectInputProps(props) && isType(props.schemaType, "reference") && ((_b = (_a = props.schemaType.options) == null ? void 0 : _a.embeddingsIndex) == null ? void 0 : _b.indexName)) {
2156
- return /* @__PURE__ */jsxRuntime.jsx(SemanticSearchReferenceInput, {
2157
- ...props
2217
+ const embeddingsIndexReferenceInput = sanity.definePlugin(defaultConfig => {
2218
+ const config = typeof defaultConfig === "object" ? defaultConfig : void 0;
2219
+ return {
2220
+ name: "@sanity/embeddings-index-reference-input",
2221
+ studio: {
2222
+ components: {
2223
+ layout: props => {
2224
+ return /* @__PURE__ */jsxRuntime.jsx(FeatureEnabledProvider, {
2225
+ children: props.renderDefault(props)
2158
2226
  });
2159
2227
  }
2160
- return props.renderDefault(props);
2228
+ }
2229
+ },
2230
+ form: {
2231
+ components: {
2232
+ input: props => {
2233
+ var _a, _b;
2234
+ const embeddingsIndexConfig = (_b = (_a = props.schemaType) == null ? void 0 : _a.options) == null ? void 0 : _b.embeddingsIndex;
2235
+ if (sanity.isObjectInputProps(props) && isType(props.schemaType, "reference") && (embeddingsIndexConfig === true || (embeddingsIndexConfig == null ? void 0 : embeddingsIndexConfig.indexName))) {
2236
+ return /* @__PURE__ */jsxRuntime.jsx(SemanticSearchReferenceInput, {
2237
+ ...props,
2238
+ defaultConfig: config
2239
+ });
2240
+ }
2241
+ return props.renderDefault(props);
2242
+ }
2161
2243
  }
2162
2244
  }
2163
- }
2245
+ };
2164
2246
  });
2165
2247
  const defaultProjection = "{...}";
2166
2248
  function useDefaultIndex(schema, dataset) {
@@ -2175,6 +2257,7 @@ function IndexFormInput(props) {
2175
2257
  var _a;
2176
2258
  const {
2177
2259
  label,
2260
+ description,
2178
2261
  index,
2179
2262
  prop,
2180
2263
  onChange,
@@ -2188,6 +2271,7 @@ function IndexFormInput(props) {
2188
2271
  })), [onChange, prop]);
2189
2272
  return /* @__PURE__ */jsxRuntime.jsx(FormInput, {
2190
2273
  label,
2274
+ description,
2191
2275
  onChange: handleChange,
2192
2276
  value: (_a = index[prop]) != null ? _a : "",
2193
2277
  readOnly,
@@ -2198,6 +2282,7 @@ function IndexFormInput(props) {
2198
2282
  function FormInput(props) {
2199
2283
  const {
2200
2284
  label,
2285
+ description,
2201
2286
  onChange,
2202
2287
  value,
2203
2288
  readOnly,
@@ -2215,6 +2300,12 @@ function FormInput(props) {
2215
2300
  htmlFor: id,
2216
2301
  children: label
2217
2302
  })
2303
+ }), description && /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2304
+ children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
2305
+ size: 1,
2306
+ muted: true,
2307
+ children: description
2308
+ })
2218
2309
  }), type === "text" ? /* @__PURE__ */jsxRuntime.jsx(ui.TextInput, {
2219
2310
  id,
2220
2311
  value,
@@ -2369,18 +2460,20 @@ function IndexEditor(props) {
2369
2460
  onChange: setIndex,
2370
2461
  readOnly: true
2371
2462
  }), /* @__PURE__ */jsxRuntime.jsx(IndexFormInput, {
2372
- label: "Projection",
2373
- placeholder: defaultIndex.projection,
2463
+ label: "Filter",
2464
+ description: "Must be a valid GROQ filter",
2465
+ placeholder: defaultIndex.filter,
2374
2466
  index,
2375
- prop: "projection",
2467
+ prop: "filter",
2376
2468
  onChange: setIndex,
2377
2469
  readOnly,
2378
2470
  type: "textarea"
2379
2471
  }), /* @__PURE__ */jsxRuntime.jsx(IndexFormInput, {
2380
- label: "Filter",
2381
- placeholder: defaultIndex.filter,
2472
+ label: "Projection",
2473
+ description: "Must be a valid GROQ projection, starting { and ending with }",
2474
+ placeholder: defaultIndex.projection,
2382
2475
  index,
2383
- prop: "filter",
2476
+ prop: "projection",
2384
2477
  onChange: setIndex,
2385
2478
  readOnly,
2386
2479
  type: "textarea"
@@ -2417,6 +2510,7 @@ function IndexList(props) {
2417
2510
  borderBottom: true,
2418
2511
  flex: 1,
2419
2512
  paddingBottom: 2,
2513
+ padding: 3,
2420
2514
  children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
2421
2515
  children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2422
2516
  flex: 1,
@@ -2471,12 +2565,15 @@ function IndexRow(props) {
2471
2565
  const onSelect = require$$0.useCallback(() => onIndexSelected(index), [onIndexSelected, index]);
2472
2566
  return /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
2473
2567
  tone: (selectedIndex == null ? void 0 : selectedIndex.indexName) === index.indexName ? "primary" : "default",
2474
- mode: (selectedIndex == null ? void 0 : selectedIndex.indexName) === index.indexName ? "default" : "bleed",
2568
+ mode: (selectedIndex == null ? void 0 : selectedIndex.indexName) === index.indexName ? "default" : "ghost",
2475
2569
  onClick: onSelect,
2570
+ padding: 3,
2476
2571
  children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
2477
2572
  children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2478
2573
  flex: 1,
2479
- children: index.indexName
2574
+ children: /* @__PURE__ */jsxRuntime.jsx("strong", {
2575
+ children: index.indexName
2576
+ })
2480
2577
  }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2481
2578
  flex: 1,
2482
2579
  children: index.dataset
@@ -2490,102 +2587,18 @@ function IndexRow(props) {
2490
2587
  })
2491
2588
  }, index.indexName);
2492
2589
  }
2493
- const NO_RESULTS = [];
2494
2590
  function QueryIndex(props) {
2495
2591
  const {
2496
2592
  indexName
2497
2593
  } = props;
2498
- const [query, setQuery] = require$$0.useState("");
2499
- const [searching, setSearching] = require$$0.useState(false);
2500
- const [results, setResults] = require$$0.useState(NO_RESULTS);
2501
- const client = useApiClient();
2502
- const search = require$$0.useCallback(queryString => {
2503
- setSearching(true);
2504
- return queryIndex({
2505
- query: queryString,
2506
- indexName,
2507
- maxResults: 5
2508
- }, client).then(setResults).finally(() => setSearching(false));
2509
- }, [client, indexName]);
2510
- const onInputChange = require$$0.useCallback(e => {
2511
- setQuery(e.currentTarget.value);
2512
- }, []);
2513
- const onKeyDown = require$$0.useCallback(e => {
2514
- if (e.key === "Enter") {
2515
- search(query).catch(console.error);
2516
- }
2517
- }, [search, query]);
2518
- return /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
2519
- space: 3,
2520
- flex: 1,
2521
- children: [/* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
2522
- flex: 1,
2523
- children: /* @__PURE__ */jsxRuntime.jsx(ui.Card, {
2524
- flex: 1,
2525
- children: /* @__PURE__ */jsxRuntime.jsx(ui.TextInput, {
2526
- iconRight: searching ? /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2527
- style: {
2528
- marginTop: 5
2529
- },
2530
- children: /* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {})
2531
- }) : icons.SearchIcon,
2532
- placeholder: "Find documents",
2533
- value: query,
2534
- disabled: searching,
2535
- onChange: onInputChange,
2536
- onKeyDown
2537
- })
2538
- })
2539
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
2540
- gap: 4,
2541
- style: {
2542
- opacity: searching ? 0.5 : 1
2543
- },
2544
- children: /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2545
- flex: 1,
2546
- children: /* @__PURE__ */jsxRuntime.jsx(ResultList, {
2547
- results,
2548
- query
2549
- })
2550
- })
2551
- })]
2552
- });
2553
- }
2554
- function ResultList(props) {
2555
- const {
2556
- results,
2557
- query
2558
- } = props;
2559
- return /* @__PURE__ */jsxRuntime.jsx(ui.Stack, {
2560
- space: 4,
2561
- height: "fill",
2562
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Stack, {
2563
- space: 2,
2564
- children: [results.map(r => /* @__PURE__ */jsxRuntime.jsx(ResultEntry, {
2565
- result: r
2566
- }, r.value.documentId)), !results.length && query ? "No results." : null]
2567
- })
2568
- });
2569
- }
2570
- function ResultEntry(props) {
2571
- const value = props.result.value;
2572
- return /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
2573
- gap: 4,
2574
- align: "center",
2575
- children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2576
- flex: 1,
2577
- children: /* @__PURE__ */jsxRuntime.jsx(DocumentPreview, {
2578
- documentId: value.documentId,
2579
- schemaTypeName: value.type,
2580
- button: true
2581
- })
2582
- }), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
2583
- children: /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
2584
- muted: true,
2585
- size: 1,
2586
- children: [Math.floor(props.result.score * 100), " %"]
2587
- })
2588
- })]
2594
+ const getEmpty = require$$0.useCallback(() => "anything", []);
2595
+ const indexConfig = require$$0.useMemo(() => ({
2596
+ indexName,
2597
+ maxResults: 8
2598
+ }), [indexName]);
2599
+ return /* @__PURE__ */jsxRuntime.jsx(SemanticSearchAutocomplete, {
2600
+ getEmptySearchValue: getEmpty,
2601
+ indexConfig
2589
2602
  });
2590
2603
  }
2591
2604
  function IndexInfo(_ref3) {