@sanity/embeddings-index-ui 1.0.3 → 1.1.1
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/README.md +33 -1
- package/dist/index.d.ts +21 -14
- package/dist/index.esm.js +303 -274
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +299 -270
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/embeddingsIndexDashboard/IndexEditor.tsx +8 -6
- package/src/embeddingsIndexDashboard/IndexFormInput.tsx +13 -3
- package/src/embeddingsIndexDashboard/IndexList.tsx +6 -3
- package/src/embeddingsIndexDashboard/QueryIndex.tsx +21 -98
- package/src/referenceInput/SemanticSearchAutocomplete.tsx +210 -0
- package/src/referenceInput/SemanticSearchReferenceInput.tsx +65 -144
- package/src/referenceInput/referencePlugin.tsx +35 -21
- package/src/schemas/typeDefExtensions.ts +21 -13
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
|
|
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
|
|
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
|
-
|
|
2000
|
-
|
|
1958
|
+
indexConfig,
|
|
1959
|
+
filterResult,
|
|
1960
|
+
getEmptySearchValue,
|
|
2001
1961
|
readOnly,
|
|
2002
|
-
|
|
2003
|
-
|
|
1962
|
+
onFocus,
|
|
1963
|
+
onBlur,
|
|
1964
|
+
onSelect,
|
|
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
|
|
1976
|
+
var _a;
|
|
2031
1977
|
setSearching(true);
|
|
2032
|
-
const
|
|
2033
|
-
const
|
|
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
|
|
1981
|
+
throw new Error("Reference option embeddingsIndex.indexName is required, but was missing");
|
|
2038
1982
|
}
|
|
2039
1983
|
queryIndex({
|
|
2040
|
-
query: queryString.trim().length ? queryString : (
|
|
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(
|
|
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,
|
|
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,190 @@ 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
|
+
const option = options.filter(r => "result" in r).find(r => r.result.value.documentId === value);
|
|
2033
|
+
if (option && onSelect) {
|
|
2034
|
+
onSelect(option.result);
|
|
2035
|
+
}
|
|
2036
|
+
}, [onSelect, options]);
|
|
2085
2037
|
return /* @__PURE__ */jsxRuntime.jsx(ui.Autocomplete, {
|
|
2086
2038
|
id,
|
|
2087
|
-
ref
|
|
2039
|
+
ref,
|
|
2088
2040
|
"data-testid": "semantic-autocomplete",
|
|
2089
2041
|
placeholder: "Type to search...",
|
|
2090
2042
|
openButton: openButtonConfig,
|
|
2091
|
-
onFocus
|
|
2043
|
+
onFocus,
|
|
2092
2044
|
onChange: handleChange,
|
|
2093
2045
|
loading: searching,
|
|
2094
|
-
onBlur
|
|
2046
|
+
onBlur,
|
|
2095
2047
|
readOnly,
|
|
2096
2048
|
filterOption: NO_FILTER,
|
|
2097
2049
|
onQueryChange: handleQueryChange,
|
|
2098
2050
|
options,
|
|
2099
2051
|
renderOption: AutocompleteOption
|
|
2100
2052
|
});
|
|
2101
|
-
}
|
|
2053
|
+
});
|
|
2102
2054
|
function AutocompleteOption(props) {
|
|
2103
|
-
|
|
2055
|
+
if ("result" in props) {
|
|
2056
|
+
const value = props.result.value;
|
|
2057
|
+
return /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
2058
|
+
mode: "bleed",
|
|
2059
|
+
padding: 1,
|
|
2060
|
+
style: {
|
|
2061
|
+
width: "100%"
|
|
2062
|
+
},
|
|
2063
|
+
children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
|
|
2064
|
+
gap: 2,
|
|
2065
|
+
align: "center",
|
|
2066
|
+
children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
2067
|
+
flex: 1,
|
|
2068
|
+
children: /* @__PURE__ */jsxRuntime.jsx(DocumentPreview, {
|
|
2069
|
+
documentId: value.documentId,
|
|
2070
|
+
schemaTypeName: value.type
|
|
2071
|
+
})
|
|
2072
|
+
}), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
2073
|
+
padding: 2,
|
|
2074
|
+
children: /* @__PURE__ */jsxRuntime.jsxs(ui.Text, {
|
|
2075
|
+
size: 1,
|
|
2076
|
+
muted: true,
|
|
2077
|
+
title: "Relevance",
|
|
2078
|
+
children: [Math.floor(props.result.score * 100), "%"]
|
|
2079
|
+
})
|
|
2080
|
+
})]
|
|
2081
|
+
})
|
|
2082
|
+
});
|
|
2083
|
+
}
|
|
2104
2084
|
return /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
2105
2085
|
mode: "bleed",
|
|
2106
2086
|
padding: 1,
|
|
2107
2087
|
style: {
|
|
2108
2088
|
width: "100%"
|
|
2109
2089
|
},
|
|
2110
|
-
|
|
2090
|
+
disabled: true,
|
|
2091
|
+
children: /* @__PURE__ */jsxRuntime.jsx(ui.Flex, {
|
|
2111
2092
|
gap: 2,
|
|
2112
2093
|
align: "center",
|
|
2113
|
-
children:
|
|
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
|
-
})]
|
|
2094
|
+
children: "No results."
|
|
2128
2095
|
})
|
|
2129
2096
|
});
|
|
2130
2097
|
}
|
|
2098
|
+
function useDebouncedValue(value, ms) {
|
|
2099
|
+
const [debouncedValue, setDebouncedValue] = require$$0.useState(value);
|
|
2100
|
+
require$$0.useEffect(() => {
|
|
2101
|
+
const timeoutId = setTimeout(() => {
|
|
2102
|
+
setDebouncedValue(value);
|
|
2103
|
+
}, ms);
|
|
2104
|
+
return () => clearTimeout(timeoutId);
|
|
2105
|
+
}, [value, ms]);
|
|
2106
|
+
return debouncedValue;
|
|
2107
|
+
}
|
|
2108
|
+
function useEmeddingsConfig(embeddingsIndexConfig, defaultConfig) {
|
|
2109
|
+
return require$$0.useMemo(() => {
|
|
2110
|
+
if (embeddingsIndexConfig === true || !embeddingsIndexConfig) {
|
|
2111
|
+
if (!(defaultConfig == null ? void 0 : defaultConfig.indexName)) {
|
|
2112
|
+
throw new Error("Default embeddingsIndex config is missing. When options.embeddingsIndex: true, embeddingsIndexReferenceInput plugin config is required.");
|
|
2113
|
+
}
|
|
2114
|
+
return defaultConfig;
|
|
2115
|
+
}
|
|
2116
|
+
const finalConfig = {
|
|
2117
|
+
...defaultConfig,
|
|
2118
|
+
...embeddingsIndexConfig
|
|
2119
|
+
};
|
|
2120
|
+
if (!(finalConfig == null ? void 0 : finalConfig.indexName)) {
|
|
2121
|
+
throw new Error("indexName is missing. Either set it in options.embeddingsIndex or configure defaults using plugin config.");
|
|
2122
|
+
}
|
|
2123
|
+
return finalConfig;
|
|
2124
|
+
}, [defaultConfig, embeddingsIndexConfig]);
|
|
2125
|
+
}
|
|
2126
|
+
function SemanticSearchReferenceInput(props) {
|
|
2127
|
+
var _a, _b;
|
|
2128
|
+
const embeddingsIndexConfig = (_b = (_a = props.schemaType) == null ? void 0 : _a.options) == null ? void 0 : _b.embeddingsIndex;
|
|
2129
|
+
const config = useEmeddingsConfig(embeddingsIndexConfig, props.defaultConfig);
|
|
2130
|
+
const defaultEnabled = config.searchMode === "embeddings";
|
|
2131
|
+
const featureState = useIsFeatureEnabledContext();
|
|
2132
|
+
const [semantic, setSemantic] = require$$0.useState(defaultEnabled);
|
|
2133
|
+
const toggleSemantic = require$$0.useCallback(() => setSemantic(current => !current), []);
|
|
2134
|
+
return /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
|
|
2135
|
+
gap: 2,
|
|
2136
|
+
flex: 1,
|
|
2137
|
+
style: {
|
|
2138
|
+
width: "100%"
|
|
2139
|
+
},
|
|
2140
|
+
children: [semantic && featureState == "loading" ? /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
2141
|
+
padding: 2,
|
|
2142
|
+
children: /* @__PURE__ */jsxRuntime.jsx(ui.Spinner, {})
|
|
2143
|
+
}) : null, semantic && featureState == "disabled" ? /* @__PURE__ */jsxRuntime.jsx(FeatureDisabledNotice, {}) : null, /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
2144
|
+
flex: 1,
|
|
2145
|
+
style: {
|
|
2146
|
+
maxHeight: 36,
|
|
2147
|
+
overflow: "hidden"
|
|
2148
|
+
},
|
|
2149
|
+
children: semantic && featureState == "enabled" ? /* @__PURE__ */jsxRuntime.jsx(SemanticSearchInput, {
|
|
2150
|
+
...props,
|
|
2151
|
+
indexConfig: config
|
|
2152
|
+
}) : props.renderDefault(props)
|
|
2153
|
+
}), /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
2154
|
+
icon: semantic ? icons.EarthGlobeIcon : icons.LinkIcon,
|
|
2155
|
+
onClick: toggleSemantic,
|
|
2156
|
+
mode: "bleed",
|
|
2157
|
+
title: semantic ? "Switch to standard reference search" : "Switch to semantic reference search"
|
|
2158
|
+
})]
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2161
|
+
function SemanticSearchInput(props) {
|
|
2162
|
+
const {
|
|
2163
|
+
indexConfig,
|
|
2164
|
+
onPathFocus,
|
|
2165
|
+
onChange,
|
|
2166
|
+
readOnly,
|
|
2167
|
+
schemaType,
|
|
2168
|
+
value
|
|
2169
|
+
} = props;
|
|
2170
|
+
const {
|
|
2171
|
+
value: currentDocument
|
|
2172
|
+
} = desk.useDocumentPane();
|
|
2173
|
+
const docRef = require$$0.useRef(currentDocument);
|
|
2174
|
+
const autocompleteRef = require$$0.useRef(null);
|
|
2175
|
+
require$$0.useEffect(() => {
|
|
2176
|
+
docRef.current = currentDocument;
|
|
2177
|
+
}, [currentDocument]);
|
|
2178
|
+
require$$0.useEffect(() => {
|
|
2179
|
+
var _a;
|
|
2180
|
+
if (value == null ? void 0 : value._ref) {
|
|
2181
|
+
(_a = autocompleteRef.current) == null ? void 0 : _a.focus();
|
|
2182
|
+
}
|
|
2183
|
+
}, []);
|
|
2184
|
+
const handleFocus = require$$0.useCallback(() => onPathFocus(["_ref"]), [onPathFocus]);
|
|
2185
|
+
const handleBlur = require$$0.useCallback(() => onPathFocus([]), [onPathFocus]);
|
|
2186
|
+
const handleChange = require$$0.useCallback(result => {
|
|
2187
|
+
if (!result) {
|
|
2188
|
+
onChange(sanity.unset());
|
|
2189
|
+
onPathFocus([]);
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
2192
|
+
const patches = [sanity.setIfMissing({}), sanity.set(schemaType.name, ["_type"]), sanity.set(publicId(result.value.documentId), ["_ref"]), sanity.unset(["_weak"]), sanity.unset(["_strengthenOnPublish"])];
|
|
2193
|
+
onChange(patches);
|
|
2194
|
+
onPathFocus([]);
|
|
2195
|
+
}, [onChange, onPathFocus, schemaType.name]);
|
|
2196
|
+
const filterResult = require$$0.useCallback(r => r.value.documentId !== publicId(docRef.current._id), [docRef]);
|
|
2197
|
+
const getEmptySearchValue = require$$0.useCallback(() => JSON.stringify(docRef.current), [docRef]);
|
|
2198
|
+
const typeFilter = require$$0.useMemo(() => schemaType.to.map(refType => refType.name), [schemaType]);
|
|
2199
|
+
return /* @__PURE__ */jsxRuntime.jsx(SemanticSearchAutocomplete, {
|
|
2200
|
+
ref: autocompleteRef,
|
|
2201
|
+
typeFilter,
|
|
2202
|
+
indexConfig,
|
|
2203
|
+
onSelect: handleChange,
|
|
2204
|
+
onFocus: handleFocus,
|
|
2205
|
+
onBlur: handleBlur,
|
|
2206
|
+
getEmptySearchValue,
|
|
2207
|
+
filterResult,
|
|
2208
|
+
readOnly
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2131
2211
|
function isType(schemaType, typeName) {
|
|
2132
2212
|
if (schemaType.name === typeName) {
|
|
2133
2213
|
return true;
|
|
@@ -2137,30 +2217,35 @@ function isType(schemaType, typeName) {
|
|
|
2137
2217
|
}
|
|
2138
2218
|
return isType(schemaType.type, typeName);
|
|
2139
2219
|
}
|
|
2140
|
-
const embeddingsIndexReferenceInput = sanity.definePlugin({
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
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
|
|
2220
|
+
const embeddingsIndexReferenceInput = sanity.definePlugin(defaultConfig => {
|
|
2221
|
+
const config = typeof defaultConfig === "object" ? defaultConfig : void 0;
|
|
2222
|
+
return {
|
|
2223
|
+
name: "@sanity/embeddings-index-reference-input",
|
|
2224
|
+
studio: {
|
|
2225
|
+
components: {
|
|
2226
|
+
layout: props => {
|
|
2227
|
+
return /* @__PURE__ */jsxRuntime.jsx(FeatureEnabledProvider, {
|
|
2228
|
+
children: props.renderDefault(props)
|
|
2158
2229
|
});
|
|
2159
2230
|
}
|
|
2160
|
-
|
|
2231
|
+
}
|
|
2232
|
+
},
|
|
2233
|
+
form: {
|
|
2234
|
+
components: {
|
|
2235
|
+
input: props => {
|
|
2236
|
+
var _a, _b;
|
|
2237
|
+
const embeddingsIndexConfig = (_b = (_a = props.schemaType) == null ? void 0 : _a.options) == null ? void 0 : _b.embeddingsIndex;
|
|
2238
|
+
if (sanity.isObjectInputProps(props) && isType(props.schemaType, "reference") && (embeddingsIndexConfig === true || (embeddingsIndexConfig == null ? void 0 : embeddingsIndexConfig.indexName))) {
|
|
2239
|
+
return /* @__PURE__ */jsxRuntime.jsx(SemanticSearchReferenceInput, {
|
|
2240
|
+
...props,
|
|
2241
|
+
defaultConfig: config
|
|
2242
|
+
});
|
|
2243
|
+
}
|
|
2244
|
+
return props.renderDefault(props);
|
|
2245
|
+
}
|
|
2161
2246
|
}
|
|
2162
2247
|
}
|
|
2163
|
-
}
|
|
2248
|
+
};
|
|
2164
2249
|
});
|
|
2165
2250
|
const defaultProjection = "{...}";
|
|
2166
2251
|
function useDefaultIndex(schema, dataset) {
|
|
@@ -2175,6 +2260,7 @@ function IndexFormInput(props) {
|
|
|
2175
2260
|
var _a;
|
|
2176
2261
|
const {
|
|
2177
2262
|
label,
|
|
2263
|
+
description,
|
|
2178
2264
|
index,
|
|
2179
2265
|
prop,
|
|
2180
2266
|
onChange,
|
|
@@ -2188,6 +2274,7 @@ function IndexFormInput(props) {
|
|
|
2188
2274
|
})), [onChange, prop]);
|
|
2189
2275
|
return /* @__PURE__ */jsxRuntime.jsx(FormInput, {
|
|
2190
2276
|
label,
|
|
2277
|
+
description,
|
|
2191
2278
|
onChange: handleChange,
|
|
2192
2279
|
value: (_a = index[prop]) != null ? _a : "",
|
|
2193
2280
|
readOnly,
|
|
@@ -2198,6 +2285,7 @@ function IndexFormInput(props) {
|
|
|
2198
2285
|
function FormInput(props) {
|
|
2199
2286
|
const {
|
|
2200
2287
|
label,
|
|
2288
|
+
description,
|
|
2201
2289
|
onChange,
|
|
2202
2290
|
value,
|
|
2203
2291
|
readOnly,
|
|
@@ -2215,6 +2303,12 @@ function FormInput(props) {
|
|
|
2215
2303
|
htmlFor: id,
|
|
2216
2304
|
children: label
|
|
2217
2305
|
})
|
|
2306
|
+
}), description && /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
2307
|
+
children: /* @__PURE__ */jsxRuntime.jsx(ui.Text, {
|
|
2308
|
+
size: 1,
|
|
2309
|
+
muted: true,
|
|
2310
|
+
children: description
|
|
2311
|
+
})
|
|
2218
2312
|
}), type === "text" ? /* @__PURE__ */jsxRuntime.jsx(ui.TextInput, {
|
|
2219
2313
|
id,
|
|
2220
2314
|
value,
|
|
@@ -2369,18 +2463,20 @@ function IndexEditor(props) {
|
|
|
2369
2463
|
onChange: setIndex,
|
|
2370
2464
|
readOnly: true
|
|
2371
2465
|
}), /* @__PURE__ */jsxRuntime.jsx(IndexFormInput, {
|
|
2372
|
-
label: "
|
|
2373
|
-
|
|
2466
|
+
label: "Filter",
|
|
2467
|
+
description: "Must be a valid GROQ filter",
|
|
2468
|
+
placeholder: defaultIndex.filter,
|
|
2374
2469
|
index,
|
|
2375
|
-
prop: "
|
|
2470
|
+
prop: "filter",
|
|
2376
2471
|
onChange: setIndex,
|
|
2377
2472
|
readOnly,
|
|
2378
2473
|
type: "textarea"
|
|
2379
2474
|
}), /* @__PURE__ */jsxRuntime.jsx(IndexFormInput, {
|
|
2380
|
-
label: "
|
|
2381
|
-
|
|
2475
|
+
label: "Projection",
|
|
2476
|
+
description: "Must be a valid GROQ projection, starting { and ending with }",
|
|
2477
|
+
placeholder: defaultIndex.projection,
|
|
2382
2478
|
index,
|
|
2383
|
-
prop: "
|
|
2479
|
+
prop: "projection",
|
|
2384
2480
|
onChange: setIndex,
|
|
2385
2481
|
readOnly,
|
|
2386
2482
|
type: "textarea"
|
|
@@ -2417,6 +2513,7 @@ function IndexList(props) {
|
|
|
2417
2513
|
borderBottom: true,
|
|
2418
2514
|
flex: 1,
|
|
2419
2515
|
paddingBottom: 2,
|
|
2516
|
+
padding: 3,
|
|
2420
2517
|
children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
|
|
2421
2518
|
children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
2422
2519
|
flex: 1,
|
|
@@ -2471,12 +2568,15 @@ function IndexRow(props) {
|
|
|
2471
2568
|
const onSelect = require$$0.useCallback(() => onIndexSelected(index), [onIndexSelected, index]);
|
|
2472
2569
|
return /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
2473
2570
|
tone: (selectedIndex == null ? void 0 : selectedIndex.indexName) === index.indexName ? "primary" : "default",
|
|
2474
|
-
mode: (selectedIndex == null ? void 0 : selectedIndex.indexName) === index.indexName ? "default" : "
|
|
2571
|
+
mode: (selectedIndex == null ? void 0 : selectedIndex.indexName) === index.indexName ? "default" : "ghost",
|
|
2475
2572
|
onClick: onSelect,
|
|
2573
|
+
padding: 3,
|
|
2476
2574
|
children: /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
|
|
2477
2575
|
children: [/* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
2478
2576
|
flex: 1,
|
|
2479
|
-
children:
|
|
2577
|
+
children: /* @__PURE__ */jsxRuntime.jsx("strong", {
|
|
2578
|
+
children: index.indexName
|
|
2579
|
+
})
|
|
2480
2580
|
}), /* @__PURE__ */jsxRuntime.jsx(ui.Box, {
|
|
2481
2581
|
flex: 1,
|
|
2482
2582
|
children: index.dataset
|
|
@@ -2490,102 +2590,31 @@ function IndexRow(props) {
|
|
|
2490
2590
|
})
|
|
2491
2591
|
}, index.indexName);
|
|
2492
2592
|
}
|
|
2493
|
-
const NO_RESULTS = [];
|
|
2494
2593
|
function QueryIndex(props) {
|
|
2495
2594
|
const {
|
|
2496
2595
|
indexName
|
|
2497
2596
|
} = props;
|
|
2498
|
-
const
|
|
2499
|
-
const
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
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) {
|
|
2597
|
+
const getEmpty = require$$0.useCallback(() => "anything", []);
|
|
2598
|
+
const indexConfig = require$$0.useMemo(() => ({
|
|
2599
|
+
indexName,
|
|
2600
|
+
maxResults: 8
|
|
2601
|
+
}), [indexName]);
|
|
2555
2602
|
const {
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
} =
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
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
|
|
2603
|
+
resolveIntentLink,
|
|
2604
|
+
navigateUrl
|
|
2605
|
+
} = router.useRouter();
|
|
2606
|
+
const onSelect = require$$0.useCallback(hit => {
|
|
2607
|
+
navigateUrl({
|
|
2608
|
+
path: resolveIntentLink("edit", {
|
|
2609
|
+
id: hit.value.documentId,
|
|
2610
|
+
type: hit.value.type
|
|
2581
2611
|
})
|
|
2582
|
-
})
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
})]
|
|
2612
|
+
});
|
|
2613
|
+
}, [resolveIntentLink, navigateUrl]);
|
|
2614
|
+
return /* @__PURE__ */jsxRuntime.jsx(SemanticSearchAutocomplete, {
|
|
2615
|
+
getEmptySearchValue: getEmpty,
|
|
2616
|
+
indexConfig,
|
|
2617
|
+
onSelect
|
|
2589
2618
|
});
|
|
2590
2619
|
}
|
|
2591
2620
|
function IndexInfo(_ref3) {
|