@constructor-io/constructorio-ui-autocomplete 1.23.19 → 1.23.21
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/constructorio-ui-autocomplete-bundled.js +12 -12
- package/lib/cjs/beaconUtils.js +13 -1
- package/lib/cjs/hooks/useCioAutocomplete.js +8 -33
- package/lib/cjs/hooks/useDownShift.js +44 -45
- package/lib/cjs/hooks/useNormalizedProps.js +53 -0
- package/lib/cjs/utils.js +8 -1
- package/lib/cjs/version.js +1 -1
- package/lib/mjs/beaconUtils.js +11 -0
- package/lib/mjs/hooks/useCioAutocomplete.js +12 -34
- package/lib/mjs/hooks/useDownShift.js +4 -4
- package/lib/mjs/hooks/useNormalizedProps.js +50 -0
- package/lib/mjs/utils.js +7 -1
- package/lib/mjs/version.js +1 -1
- package/lib/types/beaconUtils.d.ts +1 -0
- package/lib/types/hooks/useCioAutocomplete.d.ts +1 -2
- package/lib/types/hooks/useDownShift.d.ts +3 -5
- package/lib/types/hooks/useNormalizedProps.d.ts +9 -0
- package/lib/types/types.d.ts +6 -3
- package/lib/types/utils.d.ts +1 -0
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
package/lib/cjs/beaconUtils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.storeRecentAction = exports.getLastAction = exports.getRecentActions = exports.storeRecentSearch = exports.getRecentSearches = exports.storageGetArray = exports.storageGetItem = exports.cleanTerm = exports.storageSetItem = exports.getStorageEngine = exports.CONSTANTS = void 0;
|
|
3
|
+
exports.storeRecentAction = exports.getLastAction = exports.getRecentActions = exports.storeRecentSearch = exports.getRecentSearches = exports.storageGetArray = exports.storageGetItem = exports.cleanTerm = exports.storageRemoveItem = exports.storageSetItem = exports.getStorageEngine = exports.CONSTANTS = void 0;
|
|
4
4
|
// eslint-disable-next-line import/no-cycle
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
6
|
exports.CONSTANTS = {
|
|
@@ -40,6 +40,18 @@ const storageSetItem = (key, value) => {
|
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
42
|
exports.storageSetItem = storageSetItem;
|
|
43
|
+
// Remove item in storage
|
|
44
|
+
const storageRemoveItem = (key) => {
|
|
45
|
+
try {
|
|
46
|
+
const storageEngine = (0, exports.getStorageEngine)(key.scope);
|
|
47
|
+
return storageEngine.removeItem(key.key);
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
(0, utils_1.logger)(`storageRemoveItem error: ${e}`);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
exports.storageRemoveItem = storageRemoveItem;
|
|
43
55
|
/*
|
|
44
56
|
* Use the text content of the resulting HTML node(s) created from the
|
|
45
57
|
* term
|
|
@@ -12,6 +12,7 @@ const useConsoleErrors_1 = tslib_1.__importDefault(require("./useConsoleErrors")
|
|
|
12
12
|
const useSections_1 = tslib_1.__importDefault(require("./useSections"));
|
|
13
13
|
const useRecommendationsObserver_1 = tslib_1.__importDefault(require("./useRecommendationsObserver"));
|
|
14
14
|
const typeGuards_1 = require("../typeGuards");
|
|
15
|
+
const useNormalizedProps_1 = tslib_1.__importDefault(require("./useNormalizedProps"));
|
|
15
16
|
exports.defaultSections = [
|
|
16
17
|
{
|
|
17
18
|
indexSectionName: 'Search Suggestions',
|
|
@@ -22,39 +23,9 @@ exports.defaultSections = [
|
|
|
22
23
|
type: 'autocomplete',
|
|
23
24
|
},
|
|
24
25
|
];
|
|
25
|
-
const convertLegacyParametersAndAddDefaults = (sections) => sections.map((config) => {
|
|
26
|
-
if ((0, typeGuards_1.isRecommendationsSection)(config)) {
|
|
27
|
-
if (config.identifier && !config.podId) {
|
|
28
|
-
return Object.assign(Object.assign({}, config), { podId: config.identifier });
|
|
29
|
-
}
|
|
30
|
-
if (!config.indexSectionName) {
|
|
31
|
-
return Object.assign(Object.assign({}, config), { indexSectionName: 'Products' });
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
if ((0, typeGuards_1.isAutocompleteSection)(config)) {
|
|
35
|
-
if (config.identifier && !config.indexSectionName) {
|
|
36
|
-
return Object.assign(Object.assign({}, config), { indexSectionName: config.identifier });
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return config;
|
|
40
|
-
});
|
|
41
26
|
const useCioAutocomplete = (options) => {
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
const { onSubmit, onChange, openOnFocus, apiKey, cioJsClient, cioJsClientOptions, placeholder = 'What can we help you find today?', autocompleteClassName = 'cio-autocomplete', advancedParameters, defaultInput, getSearchResultsUrl, onIsOpenChange, } = memoizedOptions;
|
|
45
|
-
let { sections = exports.defaultSections, zeroStateSections } = memoizedOptions;
|
|
46
|
-
sections = (0, react_1.useMemo)(() => {
|
|
47
|
-
if (sections) {
|
|
48
|
-
return convertLegacyParametersAndAddDefaults(sections);
|
|
49
|
-
}
|
|
50
|
-
return sections;
|
|
51
|
-
}, [sections]);
|
|
52
|
-
zeroStateSections = (0, react_1.useMemo)(() => {
|
|
53
|
-
if (zeroStateSections) {
|
|
54
|
-
return convertLegacyParametersAndAddDefaults(zeroStateSections);
|
|
55
|
-
}
|
|
56
|
-
return zeroStateSections;
|
|
57
|
-
}, [zeroStateSections]);
|
|
27
|
+
const { sections, zeroStateSections, cioJsClientOptions, advancedParameters } = (0, useNormalizedProps_1.default)(options);
|
|
28
|
+
const { onSubmit, onChange, openOnFocus, apiKey, cioJsClient, placeholder = 'What can we help you find today?', autocompleteClassName = 'cio-autocomplete', defaultInput, getSearchResultsUrl } = options, rest = tslib_1.__rest(options, ["onSubmit", "onChange", "openOnFocus", "apiKey", "cioJsClient", "placeholder", "autocompleteClassName", "defaultInput", "getSearchResultsUrl"]);
|
|
58
29
|
const [query, setQuery] = (0, react_1.useState)(defaultInput || '');
|
|
59
30
|
const previousQuery = (0, usePrevious_1.default)(query);
|
|
60
31
|
const cioClient = (0, useCioClient_1.default)({ apiKey, cioJsClient, cioJsClientOptions });
|
|
@@ -63,7 +34,11 @@ const useCioAutocomplete = (options) => {
|
|
|
63
34
|
const features = (0, react_1.useMemo)(() => (0, utils_1.getFeatures)(request), [request]);
|
|
64
35
|
// Get dropdown items array from active sections (autocomplete + recommendations + custom)
|
|
65
36
|
const items = (0, react_1.useMemo)(() => (0, utils_1.getItemsForActiveSections)(activeSectionsWithData), [activeSectionsWithData]);
|
|
66
|
-
const { isOpen, getMenuProps, getLabelProps, openMenu, closeMenu, highlightedIndex, getInputProps, getItemProps: getItemPropsDownShift, } = (0, useDownShift_1.default)({ setQuery,
|
|
37
|
+
const { isOpen, getMenuProps, getLabelProps, openMenu, closeMenu, highlightedIndex, getInputProps, getItemProps: getItemPropsDownShift, } = (0, useDownShift_1.default)(Object.assign({ setQuery,
|
|
38
|
+
items,
|
|
39
|
+
onSubmit,
|
|
40
|
+
cioClient,
|
|
41
|
+
previousQuery }, rest));
|
|
67
42
|
// Log console errors
|
|
68
43
|
(0, useConsoleErrors_1.default)(sections, activeSections);
|
|
69
44
|
// Track recommendation view
|
|
@@ -1,55 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
3
4
|
const downshift_1 = require("downshift");
|
|
4
5
|
const utils_1 = require("../utils");
|
|
5
6
|
let idCounter = 0;
|
|
6
|
-
const useDownShift = (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
7
|
+
const useDownShift = (_a) => {
|
|
8
|
+
var { setQuery, items, onSubmit, cioClient, previousQuery = '' } = _a, rest = tslib_1.__rest(_a, ["setQuery", "items", "onSubmit", "cioClient", "previousQuery"]);
|
|
9
|
+
return (0, downshift_1.useCombobox)(Object.assign({ id: `cio-autocomplete-${idCounter++}`, // eslint-disable-line
|
|
10
|
+
items, itemToString: (item) => (item === null || item === void 0 ? void 0 : item.value) || '', onSelectedItemChange({ selectedItem }) {
|
|
11
|
+
var _a;
|
|
12
|
+
if (selectedItem) {
|
|
13
|
+
if (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.value) {
|
|
14
|
+
if (onSubmit)
|
|
15
|
+
onSubmit({ item: selectedItem, originalQuery: previousQuery });
|
|
16
|
+
try {
|
|
17
|
+
if ((selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.section) === 'Search Suggestions') {
|
|
18
|
+
setQuery(selectedItem.value || '');
|
|
19
|
+
(0, utils_1.trackSearchSubmit)(cioClient, selectedItem.value, {
|
|
20
|
+
originalQuery: previousQuery,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// Autocomplete Select tracking
|
|
24
|
+
// Recommendation Select tracking
|
|
25
|
+
if (selectedItem.podId && ((_a = selectedItem.data) === null || _a === void 0 ? void 0 : _a.id) && selectedItem.strategy) {
|
|
26
|
+
cioClient === null || cioClient === void 0 ? void 0 : cioClient.tracker.trackRecommendationClick({
|
|
27
|
+
itemName: selectedItem.value,
|
|
28
|
+
itemId: selectedItem.data.id,
|
|
29
|
+
variationId: selectedItem.data.variation_id,
|
|
30
|
+
podId: selectedItem.podId,
|
|
31
|
+
strategyId: selectedItem.strategy.id,
|
|
32
|
+
section: selectedItem.section,
|
|
33
|
+
resultId: selectedItem.result_id,
|
|
34
|
+
});
|
|
35
|
+
// Select tracking for all other Constructor sections:
|
|
36
|
+
// (ie: Search Suggestions, Products, Custom Cio sections, etc)
|
|
37
|
+
// This does not apply to custom user defined sections that aren't part of Constructor index
|
|
38
|
+
}
|
|
39
|
+
else if (selectedItem.result_id) {
|
|
40
|
+
(0, utils_1.trackAutocompleteSelect)(cioClient, selectedItem.value, {
|
|
41
|
+
originalQuery: previousQuery,
|
|
42
|
+
section: selectedItem.section,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
22
45
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
cioClient === null || cioClient === void 0 ? void 0 : cioClient.tracker.trackRecommendationClick({
|
|
27
|
-
itemName: selectedItem.value,
|
|
28
|
-
itemId: selectedItem.data.id,
|
|
29
|
-
variationId: selectedItem.data.variation_id,
|
|
30
|
-
podId: selectedItem.podId,
|
|
31
|
-
strategyId: selectedItem.strategy.id,
|
|
32
|
-
section: selectedItem.section,
|
|
33
|
-
resultId: selectedItem.result_id,
|
|
34
|
-
});
|
|
35
|
-
// Select tracking for all other Constructor sections:
|
|
36
|
-
// (ie: Search Suggestions, Products, Custom Cio sections, etc)
|
|
37
|
-
// This does not apply to custom user defined sections that aren't part of Constructor index
|
|
46
|
+
catch (error) {
|
|
47
|
+
// eslint-disable-next-line no-console
|
|
48
|
+
console.log(error);
|
|
38
49
|
}
|
|
39
|
-
else if (selectedItem.result_id) {
|
|
40
|
-
cioClient === null || cioClient === void 0 ? void 0 : cioClient.tracker.trackAutocompleteSelect(selectedItem.value, {
|
|
41
|
-
originalQuery: previousQuery,
|
|
42
|
-
section: selectedItem.section,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
// eslint-disable-next-line no-console
|
|
48
|
-
console.log(error);
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
onIsOpenChange,
|
|
54
|
-
});
|
|
52
|
+
} }, rest));
|
|
53
|
+
};
|
|
55
54
|
exports.default = useDownShift;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultSections = void 0;
|
|
4
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const typeGuards_1 = require("../typeGuards");
|
|
7
|
+
exports.defaultSections = [
|
|
8
|
+
{
|
|
9
|
+
indexSectionName: 'Search Suggestions',
|
|
10
|
+
type: 'autocomplete',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
indexSectionName: 'Products',
|
|
14
|
+
type: 'autocomplete',
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
const convertLegacyParametersAndAddDefaults = (sections) => sections.map((config) => {
|
|
18
|
+
if ((0, typeGuards_1.isRecommendationsSection)(config)) {
|
|
19
|
+
if (config.identifier && !config.podId) {
|
|
20
|
+
return Object.assign(Object.assign({}, config), { podId: config.identifier });
|
|
21
|
+
}
|
|
22
|
+
if (!config.indexSectionName) {
|
|
23
|
+
return Object.assign(Object.assign({}, config), { indexSectionName: 'Products' });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if ((0, typeGuards_1.isAutocompleteSection)(config)) {
|
|
27
|
+
if (config.identifier && !config.indexSectionName) {
|
|
28
|
+
return Object.assign(Object.assign({}, config), { indexSectionName: config.identifier });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return config;
|
|
32
|
+
});
|
|
33
|
+
const normalizeSections = (sections) => {
|
|
34
|
+
if (sections) {
|
|
35
|
+
return convertLegacyParametersAndAddDefaults(sections);
|
|
36
|
+
}
|
|
37
|
+
return sections;
|
|
38
|
+
};
|
|
39
|
+
// Normalize and Memoize Objects to prevent infinite rerenders if users pass object literals to useCioAutocomplete
|
|
40
|
+
const useNormalizedProps = (options) => {
|
|
41
|
+
const { sections = exports.defaultSections, zeroStateSections, cioJsClientOptions, advancedParameters, } = options;
|
|
42
|
+
const sectionsMemoized = (0, react_1.useMemo)(() => normalizeSections(sections), [JSON.stringify(sections)]);
|
|
43
|
+
const zeroStateSectionsMemoized = (0, react_1.useMemo)(() => normalizeSections(zeroStateSections), [JSON.stringify(zeroStateSections)]);
|
|
44
|
+
const cioJsClientOptionsMemoized = (0, react_1.useMemo)(() => cioJsClientOptions, [JSON.stringify(cioJsClientOptions)]);
|
|
45
|
+
const advancedParametersMemoized = (0, react_1.useMemo)(() => advancedParameters, [JSON.stringify(advancedParameters)]);
|
|
46
|
+
return {
|
|
47
|
+
sections: sectionsMemoized,
|
|
48
|
+
zeroStateSections: zeroStateSectionsMemoized,
|
|
49
|
+
cioJsClientOptions: cioJsClientOptionsMemoized,
|
|
50
|
+
advancedParameters: advancedParametersMemoized,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
exports.default = useNormalizedProps;
|
package/lib/cjs/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.logger = exports.trackSearchSubmit = exports.translate = exports.getItemsForActiveSections = exports.trackRecommendationView = exports.escapeRegExp = exports.getActiveSectionsWithData = exports.getCioClient = exports.disableStoryActions = exports.stringifyWithDefaults = exports.functionStrings = exports.getStoryParams = exports.sleep = exports.clearConstructorRequests = exports.isTrackingRequestSent = exports.toKebabCase = exports.camelToStartCase = exports.getItemPosition = exports.getFeatures = void 0;
|
|
3
|
+
exports.logger = exports.trackAutocompleteSelect = exports.trackSearchSubmit = exports.translate = exports.getItemsForActiveSections = exports.trackRecommendationView = exports.escapeRegExp = exports.getActiveSectionsWithData = exports.getCioClient = exports.disableStoryActions = exports.stringifyWithDefaults = exports.functionStrings = exports.getStoryParams = exports.sleep = exports.clearConstructorRequests = exports.isTrackingRequestSent = exports.toKebabCase = exports.camelToStartCase = exports.getItemPosition = exports.getFeatures = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const constructorio_client_javascript_1 = tslib_1.__importDefault(require("@constructor-io/constructorio-client-javascript"));
|
|
6
6
|
// eslint-disable-next-line import/no-cycle
|
|
@@ -233,6 +233,13 @@ const trackSearchSubmit = (cioClient, term, autocompleteData = {}) => {
|
|
|
233
233
|
(0, beaconUtils_1.storeRecentAction)(beaconUtils_1.CONSTANTS.SEARCH_SUBMIT);
|
|
234
234
|
};
|
|
235
235
|
exports.trackSearchSubmit = trackSearchSubmit;
|
|
236
|
+
const trackAutocompleteSelect = (cioClient, itemName, autocompleteData = {}) => {
|
|
237
|
+
cioClient === null || cioClient === void 0 ? void 0 : cioClient.tracker.trackAutocompleteSelect(itemName, autocompleteData);
|
|
238
|
+
if ((autocompleteData === null || autocompleteData === void 0 ? void 0 : autocompleteData.section) === 'Products') {
|
|
239
|
+
(0, beaconUtils_1.storageRemoveItem)(beaconUtils_1.CONSTANTS.SEARCH_TERM_STORAGE_KEY);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
exports.trackAutocompleteSelect = trackAutocompleteSelect;
|
|
236
243
|
const logger = (error) => {
|
|
237
244
|
var _a;
|
|
238
245
|
try {
|
package/lib/cjs/version.js
CHANGED
package/lib/mjs/beaconUtils.js
CHANGED
|
@@ -35,6 +35,17 @@ export const storageSetItem = (key, value) => {
|
|
|
35
35
|
return null;
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
|
+
// Remove item in storage
|
|
39
|
+
export const storageRemoveItem = (key) => {
|
|
40
|
+
try {
|
|
41
|
+
const storageEngine = getStorageEngine(key.scope);
|
|
42
|
+
return storageEngine.removeItem(key.key);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
logger(`storageRemoveItem error: ${e}`);
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
38
49
|
/*
|
|
39
50
|
* Use the text content of the resulting HTML node(s) created from the
|
|
40
51
|
* term
|
|
@@ -7,7 +7,8 @@ import { getItemPosition, getItemsForActiveSections, getFeatures, trackRecommend
|
|
|
7
7
|
import useConsoleErrors from './useConsoleErrors';
|
|
8
8
|
import useSections from './useSections';
|
|
9
9
|
import useRecommendationsObserver from './useRecommendationsObserver';
|
|
10
|
-
import {
|
|
10
|
+
import { isCustomSection, isRecommendationsSection } from '../typeGuards';
|
|
11
|
+
import useNormalizedProps from './useNormalizedProps';
|
|
11
12
|
export const defaultSections = [
|
|
12
13
|
{
|
|
13
14
|
indexSectionName: 'Search Suggestions',
|
|
@@ -18,39 +19,9 @@ export const defaultSections = [
|
|
|
18
19
|
type: 'autocomplete',
|
|
19
20
|
},
|
|
20
21
|
];
|
|
21
|
-
const convertLegacyParametersAndAddDefaults = (sections) => sections.map((config) => {
|
|
22
|
-
if (isRecommendationsSection(config)) {
|
|
23
|
-
if (config.identifier && !config.podId) {
|
|
24
|
-
return { ...config, podId: config.identifier };
|
|
25
|
-
}
|
|
26
|
-
if (!config.indexSectionName) {
|
|
27
|
-
return { ...config, indexSectionName: 'Products' };
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (isAutocompleteSection(config)) {
|
|
31
|
-
if (config.identifier && !config.indexSectionName) {
|
|
32
|
-
return { ...config, indexSectionName: config.identifier };
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return config;
|
|
36
|
-
});
|
|
37
22
|
const useCioAutocomplete = (options) => {
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const { onSubmit, onChange, openOnFocus, apiKey, cioJsClient, cioJsClientOptions, placeholder = 'What can we help you find today?', autocompleteClassName = 'cio-autocomplete', advancedParameters, defaultInput, getSearchResultsUrl, onIsOpenChange, } = memoizedOptions;
|
|
41
|
-
let { sections = defaultSections, zeroStateSections } = memoizedOptions;
|
|
42
|
-
sections = useMemo(() => {
|
|
43
|
-
if (sections) {
|
|
44
|
-
return convertLegacyParametersAndAddDefaults(sections);
|
|
45
|
-
}
|
|
46
|
-
return sections;
|
|
47
|
-
}, [sections]);
|
|
48
|
-
zeroStateSections = useMemo(() => {
|
|
49
|
-
if (zeroStateSections) {
|
|
50
|
-
return convertLegacyParametersAndAddDefaults(zeroStateSections);
|
|
51
|
-
}
|
|
52
|
-
return zeroStateSections;
|
|
53
|
-
}, [zeroStateSections]);
|
|
23
|
+
const { sections, zeroStateSections, cioJsClientOptions, advancedParameters } = useNormalizedProps(options);
|
|
24
|
+
const { onSubmit, onChange, openOnFocus, apiKey, cioJsClient, placeholder = 'What can we help you find today?', autocompleteClassName = 'cio-autocomplete', defaultInput, getSearchResultsUrl, ...rest } = options;
|
|
54
25
|
const [query, setQuery] = useState(defaultInput || '');
|
|
55
26
|
const previousQuery = usePrevious(query);
|
|
56
27
|
const cioClient = useCioClient({ apiKey, cioJsClient, cioJsClientOptions });
|
|
@@ -59,7 +30,14 @@ const useCioAutocomplete = (options) => {
|
|
|
59
30
|
const features = useMemo(() => getFeatures(request), [request]);
|
|
60
31
|
// Get dropdown items array from active sections (autocomplete + recommendations + custom)
|
|
61
32
|
const items = useMemo(() => getItemsForActiveSections(activeSectionsWithData), [activeSectionsWithData]);
|
|
62
|
-
const { isOpen, getMenuProps, getLabelProps, openMenu, closeMenu, highlightedIndex, getInputProps, getItemProps: getItemPropsDownShift, } = useDownShift({
|
|
33
|
+
const { isOpen, getMenuProps, getLabelProps, openMenu, closeMenu, highlightedIndex, getInputProps, getItemProps: getItemPropsDownShift, } = useDownShift({
|
|
34
|
+
setQuery,
|
|
35
|
+
items,
|
|
36
|
+
onSubmit,
|
|
37
|
+
cioClient,
|
|
38
|
+
previousQuery,
|
|
39
|
+
...rest,
|
|
40
|
+
});
|
|
63
41
|
// Log console errors
|
|
64
42
|
useConsoleErrors(sections, activeSections);
|
|
65
43
|
// Track recommendation view
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCombobox } from 'downshift';
|
|
2
|
-
import { trackSearchSubmit } from '../utils';
|
|
2
|
+
import { trackSearchSubmit, trackAutocompleteSelect } from '../utils';
|
|
3
3
|
let idCounter = 0;
|
|
4
|
-
const useDownShift = ({ setQuery, items, onSubmit, cioClient, previousQuery = '',
|
|
4
|
+
const useDownShift = ({ setQuery, items, onSubmit, cioClient, previousQuery = '', ...rest }) => useCombobox({
|
|
5
5
|
id: `cio-autocomplete-${idCounter++}`,
|
|
6
6
|
items,
|
|
7
7
|
itemToString: (item) => item?.value || '',
|
|
@@ -34,7 +34,7 @@ const useDownShift = ({ setQuery, items, onSubmit, cioClient, previousQuery = ''
|
|
|
34
34
|
// This does not apply to custom user defined sections that aren't part of Constructor index
|
|
35
35
|
}
|
|
36
36
|
else if (selectedItem.result_id) {
|
|
37
|
-
|
|
37
|
+
trackAutocompleteSelect(cioClient, selectedItem.value, {
|
|
38
38
|
originalQuery: previousQuery,
|
|
39
39
|
section: selectedItem.section,
|
|
40
40
|
});
|
|
@@ -47,6 +47,6 @@ const useDownShift = ({ setQuery, items, onSubmit, cioClient, previousQuery = ''
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
|
-
|
|
50
|
+
...rest,
|
|
51
51
|
});
|
|
52
52
|
export default useDownShift;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { isAutocompleteSection, isRecommendationsSection } from '../typeGuards';
|
|
4
|
+
export const defaultSections = [
|
|
5
|
+
{
|
|
6
|
+
indexSectionName: 'Search Suggestions',
|
|
7
|
+
type: 'autocomplete',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
indexSectionName: 'Products',
|
|
11
|
+
type: 'autocomplete',
|
|
12
|
+
},
|
|
13
|
+
];
|
|
14
|
+
const convertLegacyParametersAndAddDefaults = (sections) => sections.map((config) => {
|
|
15
|
+
if (isRecommendationsSection(config)) {
|
|
16
|
+
if (config.identifier && !config.podId) {
|
|
17
|
+
return { ...config, podId: config.identifier };
|
|
18
|
+
}
|
|
19
|
+
if (!config.indexSectionName) {
|
|
20
|
+
return { ...config, indexSectionName: 'Products' };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (isAutocompleteSection(config)) {
|
|
24
|
+
if (config.identifier && !config.indexSectionName) {
|
|
25
|
+
return { ...config, indexSectionName: config.identifier };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return config;
|
|
29
|
+
});
|
|
30
|
+
const normalizeSections = (sections) => {
|
|
31
|
+
if (sections) {
|
|
32
|
+
return convertLegacyParametersAndAddDefaults(sections);
|
|
33
|
+
}
|
|
34
|
+
return sections;
|
|
35
|
+
};
|
|
36
|
+
// Normalize and Memoize Objects to prevent infinite rerenders if users pass object literals to useCioAutocomplete
|
|
37
|
+
const useNormalizedProps = (options) => {
|
|
38
|
+
const { sections = defaultSections, zeroStateSections, cioJsClientOptions, advancedParameters, } = options;
|
|
39
|
+
const sectionsMemoized = useMemo(() => normalizeSections(sections), [JSON.stringify(sections)]);
|
|
40
|
+
const zeroStateSectionsMemoized = useMemo(() => normalizeSections(zeroStateSections), [JSON.stringify(zeroStateSections)]);
|
|
41
|
+
const cioJsClientOptionsMemoized = useMemo(() => cioJsClientOptions, [JSON.stringify(cioJsClientOptions)]);
|
|
42
|
+
const advancedParametersMemoized = useMemo(() => advancedParameters, [JSON.stringify(advancedParameters)]);
|
|
43
|
+
return {
|
|
44
|
+
sections: sectionsMemoized,
|
|
45
|
+
zeroStateSections: zeroStateSectionsMemoized,
|
|
46
|
+
cioJsClientOptions: cioJsClientOptionsMemoized,
|
|
47
|
+
advancedParameters: advancedParametersMemoized,
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
export default useNormalizedProps;
|
package/lib/mjs/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ConstructorIOClient from '@constructor-io/constructorio-client-javascript';
|
|
2
2
|
// eslint-disable-next-line import/no-cycle
|
|
3
|
-
import { storageSetItem, storeRecentSearch, storeRecentAction, CONSTANTS } from './beaconUtils';
|
|
3
|
+
import { storageSetItem, storageRemoveItem, storeRecentSearch, storeRecentAction, CONSTANTS, } from './beaconUtils';
|
|
4
4
|
import { isRecommendationsSection } from './typeGuards';
|
|
5
5
|
import version from './version';
|
|
6
6
|
export function getFeatures(request) {
|
|
@@ -213,6 +213,12 @@ export const trackSearchSubmit = (cioClient, term, autocompleteData = {}) => {
|
|
|
213
213
|
storeRecentSearch(term, {});
|
|
214
214
|
storeRecentAction(CONSTANTS.SEARCH_SUBMIT);
|
|
215
215
|
};
|
|
216
|
+
export const trackAutocompleteSelect = (cioClient, itemName, autocompleteData = {}) => {
|
|
217
|
+
cioClient?.tracker.trackAutocompleteSelect(itemName, autocompleteData);
|
|
218
|
+
if (autocompleteData?.section === 'Products') {
|
|
219
|
+
storageRemoveItem(CONSTANTS.SEARCH_TERM_STORAGE_KEY);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
216
222
|
export const logger = (error) => {
|
|
217
223
|
try {
|
|
218
224
|
if (typeof process !== 'undefined' && process?.env?.LOGGER) {
|
package/lib/mjs/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.23.
|
|
1
|
+
export default '1.23.21';
|
|
@@ -17,6 +17,7 @@ export declare const CONSTANTS: {
|
|
|
17
17
|
};
|
|
18
18
|
export declare const getStorageEngine: (scope: any) => Storage;
|
|
19
19
|
export declare const storageSetItem: (key: any, value: any) => void | null;
|
|
20
|
+
export declare const storageRemoveItem: (key: any) => void | null;
|
|
20
21
|
export declare const cleanTerm: (term: any) => string;
|
|
21
22
|
export declare const storageGetItem: (key: any) => string | null;
|
|
22
23
|
export declare const storageGetArray: (key: any) => any;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Section, UserDefinedSection, HTMLPropsWithCioDataAttributes, Item, UseCioAutocompleteOptions } from '../types';
|
|
2
2
|
export declare const defaultSections: UserDefinedSection[];
|
|
3
|
-
export type UseCioAutocompleteOptions = Omit<CioAutocompleteProps, 'children'>;
|
|
4
3
|
declare const useCioAutocomplete: (options: UseCioAutocompleteOptions) => {
|
|
5
4
|
query: string;
|
|
6
5
|
sections: Section[];
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import {
|
|
2
|
+
import { UseComboboxProps, UseComboboxReturnValue } from 'downshift';
|
|
3
3
|
import ConstructorIOClient from '@constructor-io/constructorio-client-javascript';
|
|
4
4
|
import { Nullable } from '@constructor-io/constructorio-client-javascript/lib/types';
|
|
5
5
|
import { Item, OnSubmit } from '../types';
|
|
6
|
-
|
|
6
|
+
interface UseDownShiftOptions extends UseComboboxProps<Item> {
|
|
7
7
|
setQuery: React.Dispatch<React.SetStateAction<string>>;
|
|
8
|
-
items: Item[];
|
|
9
8
|
onSubmit: OnSubmit;
|
|
10
9
|
previousQuery?: string;
|
|
11
10
|
cioClient: Nullable<ConstructorIOClient>;
|
|
12
|
-
|
|
13
|
-
};
|
|
11
|
+
}
|
|
14
12
|
export type DownShift = UseComboboxReturnValue<Item>;
|
|
15
13
|
type UseDownShift = (options: UseDownShiftOptions) => DownShift;
|
|
16
14
|
declare const useDownShift: UseDownShift;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { UseCioAutocompleteOptions, UserDefinedSection } from '../types';
|
|
2
|
+
export declare const defaultSections: UserDefinedSection[];
|
|
3
|
+
declare const useNormalizedProps: (options: UseCioAutocompleteOptions) => {
|
|
4
|
+
sections: UserDefinedSection[];
|
|
5
|
+
zeroStateSections: UserDefinedSection[] | undefined;
|
|
6
|
+
cioJsClientOptions: import("@constructor-io/constructorio-client-javascript").ConstructorClientOptions | undefined;
|
|
7
|
+
advancedParameters: import("../types").AdvancedParameters | undefined;
|
|
8
|
+
};
|
|
9
|
+
export default useNormalizedProps;
|
package/lib/types/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GetItemPropsOptions,
|
|
1
|
+
import { GetItemPropsOptions, UseComboboxProps } from 'downshift';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import ConstructorIOClient from '@constructor-io/constructorio-client-javascript';
|
|
4
4
|
import { IAutocompleteParameters, SearchSuggestion as SearchSuggestionFromClient, Product as ProductFromClient, Item as ItemBase, AutocompleteRequestType, ConstructorClientOptions, RecommendationsParameters } from '@constructor-io/constructorio-client-javascript/lib/types';
|
|
@@ -19,13 +19,16 @@ export interface AdvancedParametersBase {
|
|
|
19
19
|
fetchZeroStateOnFocus?: boolean;
|
|
20
20
|
}
|
|
21
21
|
export type AdvancedParameters = AdvancedParametersBase & Omit<IAutocompleteParameters, 'resultsPerSection'>;
|
|
22
|
-
|
|
22
|
+
type OptionalItemsComboboxProps<Item> = Partial<UseComboboxProps<Item>> & {
|
|
23
|
+
items?: Item[];
|
|
24
|
+
};
|
|
25
|
+
export type UseCioAutocompleteOptions = Omit<CioAutocompleteProps, 'children'>;
|
|
26
|
+
export type CioAutocompleteProps = CioClientConfig & OptionalItemsComboboxProps<Item> & {
|
|
23
27
|
openOnFocus?: boolean;
|
|
24
28
|
getSearchResultsUrl?: (item: SearchSuggestion) => string;
|
|
25
29
|
onSubmit: OnSubmit;
|
|
26
30
|
onFocus?: () => void;
|
|
27
31
|
onChange?: (input: string) => void;
|
|
28
|
-
onIsOpenChange?: (changes: UseComboboxStateChange<Item>) => void;
|
|
29
32
|
placeholder?: string;
|
|
30
33
|
children?: ReactNode;
|
|
31
34
|
sections?: UserDefinedSection[];
|
package/lib/types/utils.d.ts
CHANGED
|
@@ -43,5 +43,6 @@ export declare const trackRecommendationView: (target: HTMLElement, activeSectio
|
|
|
43
43
|
export declare const getItemsForActiveSections: (activeSectionsWithData: Section[]) => Item[];
|
|
44
44
|
export declare const translate: (word: string, translations?: Translations) => any;
|
|
45
45
|
export declare const trackSearchSubmit: (cioClient: any, term: any, autocompleteData?: {}) => void;
|
|
46
|
+
export declare const trackAutocompleteSelect: (cioClient: any, itemName: any, autocompleteData?: any) => void;
|
|
46
47
|
export declare const logger: (error: any) => void;
|
|
47
48
|
export {};
|
package/lib/types/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "1.23.
|
|
1
|
+
declare const _default: "1.23.21";
|
|
2
2
|
export default _default;
|
package/package.json
CHANGED