@usereactify/search 3.3.0 → 3.4.2
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/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useLiveConfig.d.ts +5 -0
- package/dist/hooks/useLiveConfig.js +71 -0
- package/dist/hooks/useSort.d.ts +1 -1
- package/dist/provider.d.ts +2 -2
- package/dist/provider.js +6 -2
- package/dist/result/ResultList.d.ts +1 -0
- package/dist/result/ResultList.js +8 -1
- package/dist/sensor/SensorSearch.js +3 -2
- package/package.json +1 -1
package/dist/hooks/index.d.ts
CHANGED
package/dist/hooks/index.js
CHANGED
|
@@ -23,3 +23,4 @@ __exportStar(require("./useFilterStack"), exports);
|
|
|
23
23
|
__exportStar(require("./useProductPrice"), exports);
|
|
24
24
|
__exportStar(require("./useFilterListProps"), exports);
|
|
25
25
|
__exportStar(require("./useFilterCollapsedState"), exports);
|
|
26
|
+
__exportStar(require("./useLiveConfig"), exports);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.useLiveConfig = void 0;
|
|
16
|
+
const react_1 = __importDefault(require("react"));
|
|
17
|
+
const debug = require("debug")("reactify-search:useLiveConfig");
|
|
18
|
+
// 5 minute cache expiry
|
|
19
|
+
const CACHE_EXPIRY = 5 * 60 * 1000;
|
|
20
|
+
const useLiveConfig = (shopifyPermanentDomain) => {
|
|
21
|
+
// synchronously returns cached and non-expired config from session storage
|
|
22
|
+
const cachedConfig = react_1.default.useMemo(() => {
|
|
23
|
+
var _a;
|
|
24
|
+
// skip checking cache if url search param "nocache" is set
|
|
25
|
+
const skipCache = new URLSearchParams(window.location.href.split("?")[1]).get("nocache") !==
|
|
26
|
+
null;
|
|
27
|
+
if (skipCache) {
|
|
28
|
+
debug("skipping cache");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const sessionConfig = JSON.parse((_a = window.sessionStorage.getItem("reactify-search:config")) !== null && _a !== void 0 ? _a : "null");
|
|
32
|
+
if (sessionConfig) {
|
|
33
|
+
const sessionConfigTtl = sessionConfig.expiresAt - Date.now();
|
|
34
|
+
debug(`found ${sessionConfigTtl > 0 ? "cached" : "expired"} config`);
|
|
35
|
+
if (sessionConfigTtl > 0) {
|
|
36
|
+
debug(`config expires in ${(sessionConfigTtl / 1000).toFixed()} seconds`);
|
|
37
|
+
return sessionConfig.config;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}, []);
|
|
42
|
+
const [config, setConfig] = react_1.default.useState(cachedConfig !== null && cachedConfig !== void 0 ? cachedConfig : {
|
|
43
|
+
fields: [],
|
|
44
|
+
filters: [],
|
|
45
|
+
sort: [],
|
|
46
|
+
curations: [],
|
|
47
|
+
redirects: [],
|
|
48
|
+
});
|
|
49
|
+
const [configLoading, setConfigLoading] = react_1.default.useState(cachedConfig ? false : true);
|
|
50
|
+
react_1.default.useEffect(() => {
|
|
51
|
+
// fetch remote config if no cached config is found
|
|
52
|
+
if (!cachedConfig) {
|
|
53
|
+
(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
54
|
+
debug("fetching fresh config");
|
|
55
|
+
setConfigLoading(true);
|
|
56
|
+
const json = yield fetch(`https://config.search.reactify.app/?shop=${shopifyPermanentDomain}`).then((response) => response.json());
|
|
57
|
+
setConfig(json.body);
|
|
58
|
+
setConfigLoading(false);
|
|
59
|
+
window.sessionStorage.setItem("reactify-search:config", JSON.stringify({
|
|
60
|
+
expiresAt: new Date().getTime() + CACHE_EXPIRY,
|
|
61
|
+
config: json.body,
|
|
62
|
+
}));
|
|
63
|
+
}))();
|
|
64
|
+
}
|
|
65
|
+
}, [shopifyPermanentDomain]);
|
|
66
|
+
return {
|
|
67
|
+
config,
|
|
68
|
+
configLoading,
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
exports.useLiveConfig = useLiveConfig;
|
package/dist/hooks/useSort.d.ts
CHANGED
package/dist/provider.d.ts
CHANGED
|
@@ -3,8 +3,9 @@ import type { Config, ConfigSort, ConfigFilter, ConfigCuration } from "./types/c
|
|
|
3
3
|
declare type Context = {
|
|
4
4
|
index: string;
|
|
5
5
|
config: Config;
|
|
6
|
+
configLoading: boolean;
|
|
6
7
|
shopifyPermanentDomain: string;
|
|
7
|
-
sortOption: ConfigSort;
|
|
8
|
+
sortOption: ConfigSort | undefined;
|
|
8
9
|
sortOptions: ConfigSort[];
|
|
9
10
|
searchQuery?: string;
|
|
10
11
|
filterStack?: ConfigFilter;
|
|
@@ -24,7 +25,6 @@ declare type Context = {
|
|
|
24
25
|
declare const Context: React.Context<Context | undefined>;
|
|
25
26
|
declare type Props = {
|
|
26
27
|
index: string;
|
|
27
|
-
config: Config;
|
|
28
28
|
shopifyPermanentDomain: string;
|
|
29
29
|
filterStackId?: string;
|
|
30
30
|
collection?: Collection;
|
package/dist/provider.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.useContext = exports.Provider = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const UtilityAuthenticatedReactiveBase_1 = require("./utility/UtilityAuthenticatedReactiveBase");
|
|
9
|
+
const hooks_1 = require("./hooks");
|
|
9
10
|
const debug = require("debug")("reactify-search:Provider");
|
|
10
11
|
const Context = react_1.default.createContext(undefined);
|
|
11
12
|
const defaultCredentials = {
|
|
@@ -15,7 +16,7 @@ const defaultCredentials = {
|
|
|
15
16
|
};
|
|
16
17
|
const Provider = (props) => {
|
|
17
18
|
var _a, _b;
|
|
18
|
-
const { index,
|
|
19
|
+
const { index, shopifyPermanentDomain, children, collection, instantSearch, filterStackId, noReactiveBase, additionalComponentIds, } = props;
|
|
19
20
|
const credentials = (_a = props.credentials) !== null && _a !== void 0 ? _a : defaultCredentials;
|
|
20
21
|
const theme = (_b = props.theme) !== null && _b !== void 0 ? _b : {
|
|
21
22
|
typography: {
|
|
@@ -33,6 +34,7 @@ const Provider = (props) => {
|
|
|
33
34
|
react_1.default.useEffect(() => {
|
|
34
35
|
debug("props", props);
|
|
35
36
|
}, [props]);
|
|
37
|
+
const { config, configLoading } = (0, hooks_1.useLiveConfig)(props.shopifyPermanentDomain);
|
|
36
38
|
// @todo make this hackable with a prop
|
|
37
39
|
// https://gitlab.com/reactifyapps/reactify-search-frontend/-/issues/1
|
|
38
40
|
const searchQueryFromURL = react_1.default.useMemo(() => {
|
|
@@ -64,6 +66,7 @@ const Provider = (props) => {
|
|
|
64
66
|
const contextValue = react_1.default.useMemo(() => ({
|
|
65
67
|
index,
|
|
66
68
|
config,
|
|
69
|
+
configLoading,
|
|
67
70
|
shopifyPermanentDomain,
|
|
68
71
|
collection,
|
|
69
72
|
credentials,
|
|
@@ -110,13 +113,14 @@ exports.Provider = Provider;
|
|
|
110
113
|
const useContext = () => react_1.default.useContext(Context);
|
|
111
114
|
exports.useContext = useContext;
|
|
112
115
|
const useSortState = (config, collection) => {
|
|
116
|
+
var _a;
|
|
113
117
|
const sortOptions = react_1.default.useMemo(() => {
|
|
114
118
|
const type = !!collection ? "collection" : "search";
|
|
115
119
|
return config.sort
|
|
116
120
|
.sort((a, b) => `${a.position}`.localeCompare(`${b.position}`))
|
|
117
121
|
.filter(({ visibility }) => ["all", type].includes(visibility));
|
|
118
122
|
}, [config, collection]);
|
|
119
|
-
const [sortOptionState, setSortOptionState] = react_1.default.useState(sortOptions[0].id);
|
|
123
|
+
const [sortOptionState, setSortOptionState] = react_1.default.useState((_a = sortOptions[0]) === null || _a === void 0 ? void 0 : _a.id);
|
|
120
124
|
const sortOption = react_1.default.useMemo(() => sortOptions.find(({ id }) => id === sortOptionState) || sortOptions[0], [sortOptions, sortOptionState]);
|
|
121
125
|
const setSortOption = react_1.default.useCallback((sortOptionId) => setSortOptionState(sortOptionId), []);
|
|
122
126
|
return react_1.default.useMemo(() => ({ sortOptions, sortOption, setSortOption }), [sortOption, sortOptions, setSortOption]);
|
|
@@ -14,6 +14,7 @@ declare type Props = {
|
|
|
14
14
|
pageSize?: number;
|
|
15
15
|
gridColumns?: number;
|
|
16
16
|
listClassName?: string;
|
|
17
|
+
renderBooting?: () => JSX.Element | null;
|
|
17
18
|
renderLoading?: () => JSX.Element | null;
|
|
18
19
|
renderNoResults?: () => JSX.Element | null;
|
|
19
20
|
renderResultCard?: Parameters<typeof ResultCard>[0]["render"];
|
|
@@ -11,6 +11,7 @@ const ResultPagination_1 = require("./ResultPagination");
|
|
|
11
11
|
const ResultCardCallout_1 = require("./ResultCardCallout");
|
|
12
12
|
const ResultLoadMoreButton_1 = require("./ResultLoadMoreButton");
|
|
13
13
|
const ResultPaginationNextPrev_1 = require("./ResultPaginationNextPrev");
|
|
14
|
+
const provider_1 = require("../provider");
|
|
14
15
|
const hooks_1 = require("../hooks");
|
|
15
16
|
const elastic_1 = require("../types/elastic");
|
|
16
17
|
const ResultList = (props) => {
|
|
@@ -22,9 +23,10 @@ const ResultList = (props) => {
|
|
|
22
23
|
};
|
|
23
24
|
exports.ResultList = ResultList;
|
|
24
25
|
const ResultListInner = (props) => {
|
|
25
|
-
const { gridColumns, renderError, renderAfter, renderBefore, renderLoading, listClassName, renderResults, renderNoResults, renderResultCard, renderLoadMoreButton, renderResultCardCallout, reactivesearchResultProps, } = props;
|
|
26
|
+
const { gridColumns, renderError, renderAfter, renderBefore, renderBooting, renderLoading, listClassName, renderResults, renderNoResults, renderResultCard, renderLoadMoreButton, renderResultCardCallout, reactivesearchResultProps, } = props;
|
|
26
27
|
const filterStack = (0, hooks_1.useFilterStack)();
|
|
27
28
|
const { instantSearch } = (0, hooks_1.useSearch)();
|
|
29
|
+
const { configLoading } = (0, provider_1.useContext)();
|
|
28
30
|
const initialSearchHasRun = react_1.default.useMemo(() => "undefined" !==
|
|
29
31
|
typeof reactivesearchResultProps.resultStats.numberOfResults, [reactivesearchResultProps]);
|
|
30
32
|
const styleProp = react_1.default.useMemo(() => ({
|
|
@@ -32,6 +34,11 @@ const ResultListInner = (props) => {
|
|
|
32
34
|
gridTemplateColumns: `repeat(${gridColumns !== null && gridColumns !== void 0 ? gridColumns : 4}, minmax(0, 1fr))`,
|
|
33
35
|
}), [gridColumns]);
|
|
34
36
|
const resultProps = react_1.default.useMemo(() => (Object.assign(Object.assign({}, reactivesearchResultProps), { products: reactivesearchResultProps.data.filter((document) => elastic_1.ElasticDocumentType.Product === document.type || !document.type), callouts: reactivesearchResultProps.data.filter((document) => elastic_1.ElasticDocumentType.Callout === document.type) })), [reactivesearchResultProps]);
|
|
37
|
+
if (configLoading) {
|
|
38
|
+
if (renderBooting)
|
|
39
|
+
return renderBooting();
|
|
40
|
+
return react_1.default.createElement("div", null, "Loading...");
|
|
41
|
+
}
|
|
35
42
|
if (reactivesearchResultProps.error) {
|
|
36
43
|
if (renderError)
|
|
37
44
|
return renderError({ error: reactivesearchResultProps.error });
|
|
@@ -11,9 +11,10 @@ const SensorSearch = () => {
|
|
|
11
11
|
const { fields } = (0, hooks_1.useConfig)();
|
|
12
12
|
const { searchQuery } = (0, hooks_1.useSearch)();
|
|
13
13
|
// ignore search fields only set for instant search
|
|
14
|
-
const searchFields = react_1.default.useMemo(() => fields.filter((field) => ["always_search", "search_page"].includes(field.searchType)), []);
|
|
15
|
-
if (!searchQuery)
|
|
14
|
+
const searchFields = react_1.default.useMemo(() => fields.filter((field) => ["always_search", "search_page"].includes(field.searchType)), [fields]);
|
|
15
|
+
if (!searchQuery || !searchFields.length) {
|
|
16
16
|
return null;
|
|
17
|
+
}
|
|
17
18
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
18
19
|
react_1.default.createElement(DataSearch_1.default, { fuzziness: 1, queryFormat: "and", autosuggest: false, value: searchQuery, componentId: "SensorSearch", style: { display: "none" }, dataField: searchFields.map((field) => field.field), fieldWeights: searchFields.map((field) => field.importance), customQuery: (value, props) => {
|
|
19
20
|
const { dataField, fieldWeights } = props;
|