@constructor-io/constructorio-ui-autocomplete 1.23.27 → 1.23.29
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 +9 -9
- package/lib/cjs/components/Autocomplete/AutocompleteResults/AutocompleteResults.js +2 -2
- package/lib/cjs/components/Autocomplete/SectionItem/SectionItem.js +2 -2
- package/lib/cjs/components/Autocomplete/SectionItem/SectionItemText.js +2 -2
- package/lib/cjs/components/Autocomplete/SectionItemsList/SectionItemsList.js +5 -4
- package/lib/cjs/hooks/useCioAutocomplete.js +12 -9
- package/lib/cjs/hooks/useCioClient.js +2 -2
- package/lib/cjs/hooks/useDownShift.js +3 -3
- package/lib/cjs/hooks/useSections/useActiveSectionsWithData.js +2 -2
- package/lib/cjs/hooks/useSections/useRemoveSections.js +2 -2
- package/lib/cjs/{beaconUtils.js → utils/beaconUtils.js} +6 -65
- package/lib/cjs/utils/features.js +61 -0
- package/lib/cjs/utils/format.js +35 -0
- package/lib/cjs/utils/helpers.js +149 -0
- package/lib/cjs/utils/storage.js +63 -0
- package/lib/cjs/utils/tracking.js +52 -0
- package/lib/cjs/version.js +1 -1
- package/lib/mjs/components/Autocomplete/AutocompleteResults/AutocompleteResults.js +1 -1
- package/lib/mjs/components/Autocomplete/SectionItem/SectionItem.js +1 -1
- package/lib/mjs/components/Autocomplete/SectionItem/SectionItemText.js +1 -1
- package/lib/mjs/components/Autocomplete/SectionItemsList/SectionItemsList.js +2 -1
- package/lib/mjs/hooks/useCioAutocomplete.js +4 -1
- package/lib/mjs/hooks/useCioClient.js +1 -1
- package/lib/mjs/hooks/useDownShift.js +1 -1
- package/lib/mjs/hooks/useSections/useActiveSectionsWithData.js +1 -1
- package/lib/mjs/hooks/useSections/useRemoveSections.js +1 -1
- package/lib/mjs/{beaconUtils.js → utils/beaconUtils.js} +1 -55
- package/lib/mjs/utils/features.js +56 -0
- package/lib/mjs/utils/format.js +29 -0
- package/lib/mjs/{utils.js → utils/helpers.js} +1 -98
- package/lib/mjs/utils/storage.js +55 -0
- package/lib/mjs/utils/tracking.js +41 -0
- package/lib/mjs/version.js +1 -1
- package/lib/types/{beaconUtils.d.ts → utils/beaconUtils.d.ts} +0 -5
- package/lib/types/utils/features.d.ts +9 -0
- package/lib/types/utils/format.d.ts +5 -0
- package/lib/types/{utils.d.ts → utils/helpers.d.ts} +2 -16
- package/lib/types/utils/storage.d.ts +5 -0
- package/lib/types/utils/tracking.d.ts +7 -0
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/lib/cjs/utils.js +0 -259
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.storageRemoveItem = exports.storageSetItem = exports.storageGetArray = exports.storageGetItem = exports.getStorageEngine = void 0;
|
|
4
|
+
const helpers_1 = require("./helpers");
|
|
5
|
+
// Return storage engine based on scope
|
|
6
|
+
const getStorageEngine = (scope) => {
|
|
7
|
+
if (scope === 'local') {
|
|
8
|
+
return localStorage;
|
|
9
|
+
}
|
|
10
|
+
return sessionStorage;
|
|
11
|
+
};
|
|
12
|
+
exports.getStorageEngine = getStorageEngine;
|
|
13
|
+
// Retrieves item from storage for key
|
|
14
|
+
const storageGetItem = (key) => {
|
|
15
|
+
try {
|
|
16
|
+
const storageEngine = (0, exports.getStorageEngine)(key.scope);
|
|
17
|
+
return storageEngine.getItem(key.key);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
(0, helpers_1.logger)(`storageGetItem error: ${e}`);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
exports.storageGetItem = storageGetItem;
|
|
25
|
+
// Retrieve array from storage
|
|
26
|
+
const storageGetArray = (key) => {
|
|
27
|
+
const item = (0, exports.storageGetItem)(key);
|
|
28
|
+
if (item) {
|
|
29
|
+
try {
|
|
30
|
+
const array = JSON.parse(item);
|
|
31
|
+
return array;
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
(0, helpers_1.logger)(`storageGetArray error: ${e}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
};
|
|
39
|
+
exports.storageGetArray = storageGetArray;
|
|
40
|
+
// Set item in storage
|
|
41
|
+
const storageSetItem = (key, value) => {
|
|
42
|
+
try {
|
|
43
|
+
const storageEngine = (0, exports.getStorageEngine)(key.scope);
|
|
44
|
+
return storageEngine.setItem(key.key, value);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
(0, helpers_1.logger)(`storageSetItem error: ${e}`);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
exports.storageSetItem = storageSetItem;
|
|
52
|
+
// Remove item in storage
|
|
53
|
+
const storageRemoveItem = (key) => {
|
|
54
|
+
try {
|
|
55
|
+
const storageEngine = (0, exports.getStorageEngine)(key.scope);
|
|
56
|
+
return storageEngine.removeItem(key.key);
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
(0, helpers_1.logger)(`storageRemoveItem error: ${e}`);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
exports.storageRemoveItem = storageRemoveItem;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.trackAutocompleteSelect = exports.trackSearchSubmit = exports.trackRecommendationView = exports.isTrackingRequestSent = void 0;
|
|
4
|
+
const typeGuards_1 = require("../typeGuards");
|
|
5
|
+
// eslint-disable-next-line import/no-cycle
|
|
6
|
+
const beaconUtils_1 = require("./beaconUtils");
|
|
7
|
+
const storage_1 = require("./storage");
|
|
8
|
+
function isTrackingRequestSent(trackingRequestUrl) {
|
|
9
|
+
var _a, _b;
|
|
10
|
+
// eslint-disable-next-line
|
|
11
|
+
const trackingRequestsQueue = (_a = window.localStorage) === null || _a === void 0 ? void 0 : _a._constructorio_requests;
|
|
12
|
+
return (trackingRequestsQueue &&
|
|
13
|
+
((_b = JSON.parse(trackingRequestsQueue)) === null || _b === void 0 ? void 0 : _b.some((request) => { var _a; return (_a = request === null || request === void 0 ? void 0 : request.url) === null || _a === void 0 ? void 0 : _a.includes(trackingRequestUrl); })));
|
|
14
|
+
}
|
|
15
|
+
exports.isTrackingRequestSent = isTrackingRequestSent;
|
|
16
|
+
const trackRecommendationView = (target, activeSectionsWithData, cioClient) => {
|
|
17
|
+
if (target.dataset.cnstrcRecommendationsPodId) {
|
|
18
|
+
// Pull recommendations from activeSectionsWithData by podId surfaced on target
|
|
19
|
+
const recommendationSection = activeSectionsWithData.find((section) => (0, typeGuards_1.isRecommendationsSection)(section) &&
|
|
20
|
+
section.podId === target.dataset.cnstrcRecommendationsPodId);
|
|
21
|
+
const recommendationItems = recommendationSection === null || recommendationSection === void 0 ? void 0 : recommendationSection.data.map((item) => {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
return ({
|
|
24
|
+
itemId: (_a = item.data) === null || _a === void 0 ? void 0 : _a.id,
|
|
25
|
+
itemName: item.value,
|
|
26
|
+
variationId: (_b = item.data) === null || _b === void 0 ? void 0 : _b.variation_id,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
cioClient === null || cioClient === void 0 ? void 0 : cioClient.tracker.trackRecommendationView({
|
|
30
|
+
podId: target.dataset.cnstrcRecommendationsPodId,
|
|
31
|
+
numResultsViewed: (recommendationItems === null || recommendationItems === void 0 ? void 0 : recommendationItems.length) || 0,
|
|
32
|
+
url: window.location.href,
|
|
33
|
+
section: target.dataset.cnstrcSection,
|
|
34
|
+
items: recommendationItems,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
exports.trackRecommendationView = trackRecommendationView;
|
|
39
|
+
const trackSearchSubmit = (cioClient, term, autocompleteData = {}) => {
|
|
40
|
+
cioClient === null || cioClient === void 0 ? void 0 : cioClient.tracker.trackSearchSubmit(term, autocompleteData);
|
|
41
|
+
(0, storage_1.storageSetItem)(beaconUtils_1.CONSTANTS.SEARCH_TERM_STORAGE_KEY, term);
|
|
42
|
+
(0, beaconUtils_1.storeRecentSearch)(term, {});
|
|
43
|
+
(0, beaconUtils_1.storeRecentAction)(beaconUtils_1.CONSTANTS.SEARCH_SUBMIT);
|
|
44
|
+
};
|
|
45
|
+
exports.trackSearchSubmit = trackSearchSubmit;
|
|
46
|
+
const trackAutocompleteSelect = (cioClient, itemName, autocompleteData = {}) => {
|
|
47
|
+
cioClient === null || cioClient === void 0 ? void 0 : cioClient.tracker.trackAutocompleteSelect(itemName, autocompleteData);
|
|
48
|
+
if ((autocompleteData === null || autocompleteData === void 0 ? void 0 : autocompleteData.section) === 'Products') {
|
|
49
|
+
(0, storage_1.storageRemoveItem)(beaconUtils_1.CONSTANTS.SEARCH_TERM_STORAGE_KEY);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
exports.trackAutocompleteSelect = trackAutocompleteSelect;
|
package/lib/cjs/version.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
|
-
import { toKebabCase } from '../../../utils';
|
|
2
|
+
import { toKebabCase } from '../../../utils/format';
|
|
3
3
|
import { CioAutocompleteContext } from '../CioAutocompleteProvider';
|
|
4
4
|
import SectionItemsList from '../SectionItemsList/SectionItemsList';
|
|
5
5
|
import CloseIcon from './CloseIcon';
|
|
@@ -2,7 +2,7 @@ import React, { useContext } from 'react';
|
|
|
2
2
|
import { CioAutocompleteContext } from '../CioAutocompleteProvider';
|
|
3
3
|
import { isProduct, isInGroupSuggestion, isSearchSuggestion } from '../../../typeGuards';
|
|
4
4
|
import SectionItemText from './SectionItemText';
|
|
5
|
-
import { translate } from '../../../utils';
|
|
5
|
+
import { translate } from '../../../utils/helpers';
|
|
6
6
|
import SearchSuggestionItem from './SearchSuggestionItem';
|
|
7
7
|
export default function SectionItem(props) {
|
|
8
8
|
const { item, children, displaySearchTermHighlights } = props;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { isInGroupSuggestion } from '../../../typeGuards';
|
|
3
|
-
import { escapeRegExp } from '../../../utils';
|
|
3
|
+
import { escapeRegExp } from '../../../utils/helpers';
|
|
4
4
|
export default function SectionItemText({ item, query, highlightSearchTerm, }) {
|
|
5
5
|
const itemText = isInGroupSuggestion(item) ? item.groupName : item.value;
|
|
6
6
|
if (highlightSearchTerm) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import SectionItem from '../SectionItem/SectionItem';
|
|
3
3
|
import CustomSectionItem from '../SectionItem/CustomSectionItem';
|
|
4
|
-
import {
|
|
4
|
+
import { translate } from '../../../utils/helpers';
|
|
5
|
+
import { camelToStartCase } from '../../../utils/format';
|
|
5
6
|
import { CioAutocompleteContext } from '../CioAutocompleteProvider';
|
|
6
7
|
import NoResults from '../AutocompleteResults/NoResults';
|
|
7
8
|
// eslint-disable-next-line func-names
|
|
@@ -3,7 +3,10 @@ import { useMemo, useState } from 'react';
|
|
|
3
3
|
import useCioClient from './useCioClient';
|
|
4
4
|
import useDownShift from './useDownShift';
|
|
5
5
|
import usePrevious from './usePrevious';
|
|
6
|
-
import { getItemPosition, getItemsForActiveSections
|
|
6
|
+
import { getItemPosition, getItemsForActiveSections } from '../utils/helpers';
|
|
7
|
+
import { toKebabCase } from '../utils/format';
|
|
8
|
+
import { trackRecommendationView, trackSearchSubmit } from '../utils/tracking';
|
|
9
|
+
import { getFeatures } from '../utils/features';
|
|
7
10
|
import useConsoleErrors from './useConsoleErrors';
|
|
8
11
|
import useSections from './useSections';
|
|
9
12
|
import useRecommendationsObserver from './useRecommendationsObserver';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import { getCioClient } from '../utils';
|
|
2
|
+
import { getCioClient } from '../utils/helpers';
|
|
3
3
|
const useCioClient = ({ apiKey, cioJsClient, cioJsClientOptions }) => {
|
|
4
4
|
if (!apiKey && !cioJsClient) {
|
|
5
5
|
// eslint-disable-next-line no-console
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useCombobox } from 'downshift';
|
|
2
|
-
import { trackSearchSubmit, trackAutocompleteSelect } from '../utils';
|
|
2
|
+
import { trackSearchSubmit, trackAutocompleteSelect } from '../utils/tracking';
|
|
3
3
|
let idCounter = 0;
|
|
4
4
|
const useDownShift = ({ setQuery, items, onSubmit, cioClient, previousQuery = '', ...rest }) => useCombobox({
|
|
5
5
|
id: `cio-autocomplete-${idCounter++}`,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable max-params */
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
|
-
import { getActiveSectionsWithData } from '../../utils';
|
|
3
|
+
import { getActiveSectionsWithData } from '../../utils/helpers';
|
|
4
4
|
export default function useActiveSectionsWithData(sectionsResults, activeSections, sectionsRefs, query, podsData) {
|
|
5
5
|
const [activeSectionsWithData, setActiveSectionsWithData] = useState([]);
|
|
6
6
|
// Add to active sections the results data and refs when autocomplete results or recommendation results fetched
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable max-params */
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
|
-
import { getFeatures } from '../../utils';
|
|
3
|
+
import { getFeatures } from '../../utils/features';
|
|
4
4
|
export default function useRemoveSections(sections, podsData, setActiveSections, showZeroStateSections, zeroStateSections) {
|
|
5
5
|
// Remove sections if necessary
|
|
6
6
|
useEffect(() => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// eslint-disable-next-line import/no-cycle
|
|
2
|
-
import {
|
|
2
|
+
import { storageGetArray, storageSetItem } from './storage';
|
|
3
3
|
export const CONSTANTS = {
|
|
4
4
|
SEARCH_SUBMIT: 'SEARCH_SUBMIT',
|
|
5
5
|
RECENT_ACTIONS_STORAGE_KEY: {
|
|
@@ -17,35 +17,6 @@ export const CONSTANTS = {
|
|
|
17
17
|
RECENT_SEARCHES_STORAGE_COUNT: 100,
|
|
18
18
|
RECENT_ACTION_STORAGE_COUNT: 5,
|
|
19
19
|
};
|
|
20
|
-
// Return storage engine based on scope
|
|
21
|
-
export const getStorageEngine = (scope) => {
|
|
22
|
-
if (scope === 'local') {
|
|
23
|
-
return localStorage;
|
|
24
|
-
}
|
|
25
|
-
return sessionStorage;
|
|
26
|
-
};
|
|
27
|
-
// Set item in storage
|
|
28
|
-
export const storageSetItem = (key, value) => {
|
|
29
|
-
try {
|
|
30
|
-
const storageEngine = getStorageEngine(key.scope);
|
|
31
|
-
return storageEngine.setItem(key.key, value);
|
|
32
|
-
}
|
|
33
|
-
catch (e) {
|
|
34
|
-
logger(`storageSetItem error: ${e}`);
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
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
|
-
};
|
|
49
20
|
/*
|
|
50
21
|
* Use the text content of the resulting HTML node(s) created from the
|
|
51
22
|
* term
|
|
@@ -62,31 +33,6 @@ export const cleanTerm = (term) => {
|
|
|
62
33
|
const texts = [...nodes].map((node) => node.innerText || node.textContent);
|
|
63
34
|
return texts.join('');
|
|
64
35
|
};
|
|
65
|
-
// Retrieves item from storage for key
|
|
66
|
-
export const storageGetItem = (key) => {
|
|
67
|
-
try {
|
|
68
|
-
const storageEngine = getStorageEngine(key.scope);
|
|
69
|
-
return storageEngine.getItem(key.key);
|
|
70
|
-
}
|
|
71
|
-
catch (e) {
|
|
72
|
-
logger(`storageGetItem error: ${e}`);
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
// Retrieve array from storage
|
|
77
|
-
export const storageGetArray = (key) => {
|
|
78
|
-
const item = storageGetItem(key);
|
|
79
|
-
if (item) {
|
|
80
|
-
try {
|
|
81
|
-
const array = JSON.parse(item);
|
|
82
|
-
return array;
|
|
83
|
-
}
|
|
84
|
-
catch (e) {
|
|
85
|
-
logger(`storageGetArray error: ${e}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return null;
|
|
89
|
-
};
|
|
90
36
|
/*
|
|
91
37
|
* Returns a list of recent searches
|
|
92
38
|
*/
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { storageGetItem } from './storage';
|
|
2
|
+
const AUTOSUGGEST_CUSTOM_UI_VARIANTS = [
|
|
3
|
+
'custom_autosuggest_ui_result_count',
|
|
4
|
+
'custom_autosuggest_ui_image',
|
|
5
|
+
'custom_autosuggest_ui_image_result_count',
|
|
6
|
+
'custom_autosuggest_ui_disable_recommendations_in_zero_state',
|
|
7
|
+
];
|
|
8
|
+
const AUTOSUGGEST_CUSTOM_UI_STORAGE_KEY = {
|
|
9
|
+
scope: 'session',
|
|
10
|
+
key: '_constructorio_custom_autosuggest_ui',
|
|
11
|
+
};
|
|
12
|
+
const isCustomAutosuggestUiVariant = (variant) => AUTOSUGGEST_CUSTOM_UI_VARIANTS.includes(variant);
|
|
13
|
+
const getCustomUiVariantFromStorage = () => {
|
|
14
|
+
const item = storageGetItem(AUTOSUGGEST_CUSTOM_UI_STORAGE_KEY);
|
|
15
|
+
return item && isCustomAutosuggestUiVariant(item) ? item : null;
|
|
16
|
+
};
|
|
17
|
+
// eslint-disable-next-line import/prefer-default-export
|
|
18
|
+
export function getFeatures(request) {
|
|
19
|
+
let featureDisplaySearchSuggestionImages = false;
|
|
20
|
+
let featureDisplaySearchSuggestionResultCounts = false;
|
|
21
|
+
let featureDisplayZeroStateRecommendations = true;
|
|
22
|
+
let customAutosuggestUi = null;
|
|
23
|
+
if (request?.features?.custom_autosuggest_ui === true &&
|
|
24
|
+
isCustomAutosuggestUiVariant(request?.feature_variants?.custom_autosuggest_ui)) {
|
|
25
|
+
customAutosuggestUi = request?.feature_variants?.custom_autosuggest_ui ?? null;
|
|
26
|
+
}
|
|
27
|
+
// If a variant is set in the session storage, override the request variant
|
|
28
|
+
const customVariantFromStorage = getCustomUiVariantFromStorage();
|
|
29
|
+
if (customVariantFromStorage) {
|
|
30
|
+
customAutosuggestUi = customVariantFromStorage;
|
|
31
|
+
}
|
|
32
|
+
if (customAutosuggestUi !== null) {
|
|
33
|
+
switch (customAutosuggestUi) {
|
|
34
|
+
case 'custom_autosuggest_ui_result_count':
|
|
35
|
+
featureDisplaySearchSuggestionResultCounts = true;
|
|
36
|
+
break;
|
|
37
|
+
case 'custom_autosuggest_ui_image':
|
|
38
|
+
featureDisplaySearchSuggestionImages = true;
|
|
39
|
+
break;
|
|
40
|
+
case 'custom_autosuggest_ui_image_result_count':
|
|
41
|
+
featureDisplaySearchSuggestionImages = true;
|
|
42
|
+
featureDisplaySearchSuggestionResultCounts = true;
|
|
43
|
+
break;
|
|
44
|
+
case 'custom_autosuggest_ui_disable_recommendations_in_zero_state':
|
|
45
|
+
featureDisplayZeroStateRecommendations = false;
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
featureDisplaySearchSuggestionImages,
|
|
53
|
+
featureDisplaySearchSuggestionResultCounts,
|
|
54
|
+
featureDisplayZeroStateRecommendations,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { functionStrings } from './helpers';
|
|
2
|
+
export const camelToStartCase = (camelCaseString) => camelCaseString
|
|
3
|
+
// insert a space between lower & upper
|
|
4
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
5
|
+
// space before last upper in a sequence followed by lower
|
|
6
|
+
.replace(/\b([A-Z]+)([A-Z])([a-z])/, '$1 $2$3')
|
|
7
|
+
// uppercase the first letter
|
|
8
|
+
.replace(/([a-zA-Z])/, (str) => str.toUpperCase());
|
|
9
|
+
export const toKebabCase = (str) => str
|
|
10
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
11
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
12
|
+
.replace(/[\s_]+/g, '-')
|
|
13
|
+
.toLowerCase();
|
|
14
|
+
export const stringifyWithDefaults = (obj) => {
|
|
15
|
+
// Stringify non-function values normally. Add a template block for functions to be replaced later
|
|
16
|
+
let res = JSON.stringify(obj, (key, value) => (value instanceof Function ? `${key}_CODE` : value), ' ');
|
|
17
|
+
// Replace template blocks with function strings
|
|
18
|
+
Array.from(res.matchAll(/"(\w*)_CODE"/g)).forEach((match) => {
|
|
19
|
+
const [codePlaceholder, key] = match;
|
|
20
|
+
const functionString = functionStrings[key];
|
|
21
|
+
if (functionString) {
|
|
22
|
+
res = res.replaceAll(codePlaceholder, functionString);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.error(`Function string for ${key} not found.`); // eslint-disable-line
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return res;
|
|
29
|
+
};
|
|
@@ -1,60 +1,10 @@
|
|
|
1
1
|
import ConstructorIOClient from '@constructor-io/constructorio-client-javascript';
|
|
2
|
-
|
|
3
|
-
import { storageSetItem, storageRemoveItem, storeRecentSearch, storeRecentAction, CONSTANTS, } from './beaconUtils';
|
|
4
|
-
import { isRecommendationsSection } from './typeGuards';
|
|
5
|
-
import version from './version';
|
|
6
|
-
export function getFeatures(request) {
|
|
7
|
-
let featureDisplaySearchSuggestionImages = false;
|
|
8
|
-
let featureDisplaySearchSuggestionResultCounts = false;
|
|
9
|
-
let featureDisplayZeroStateRecommendations = true;
|
|
10
|
-
if (request?.features?.custom_autosuggest_ui === true) {
|
|
11
|
-
switch (request?.feature_variants?.custom_autosuggest_ui) {
|
|
12
|
-
case 'custom_autosuggest_ui_result_count':
|
|
13
|
-
featureDisplaySearchSuggestionResultCounts = true;
|
|
14
|
-
break;
|
|
15
|
-
case 'custom_autosuggest_ui_image':
|
|
16
|
-
featureDisplaySearchSuggestionImages = true;
|
|
17
|
-
break;
|
|
18
|
-
case 'custom_autosuggest_ui_image_result_count':
|
|
19
|
-
featureDisplaySearchSuggestionImages = true;
|
|
20
|
-
featureDisplaySearchSuggestionResultCounts = true;
|
|
21
|
-
break;
|
|
22
|
-
case 'custom_autosuggest_ui_disable_recommendations_in_zero_state':
|
|
23
|
-
featureDisplayZeroStateRecommendations = false;
|
|
24
|
-
break;
|
|
25
|
-
default:
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return {
|
|
30
|
-
featureDisplaySearchSuggestionImages,
|
|
31
|
-
featureDisplaySearchSuggestionResultCounts,
|
|
32
|
-
featureDisplayZeroStateRecommendations,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
2
|
+
import version from '../version';
|
|
35
3
|
export const getItemPosition = ({ item, items }) => {
|
|
36
4
|
const index = items.findIndex((itemInFlatList) => itemInFlatList?.id === item?.id);
|
|
37
5
|
const sectionId = items[index]?.section;
|
|
38
6
|
return { sectionId, index };
|
|
39
7
|
};
|
|
40
|
-
export const camelToStartCase = (camelCaseString) => camelCaseString
|
|
41
|
-
// insert a space between lower & upper
|
|
42
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
43
|
-
// space before last upper in a sequence followed by lower
|
|
44
|
-
.replace(/\b([A-Z]+)([A-Z])([a-z])/, '$1 $2$3')
|
|
45
|
-
// uppercase the first letter
|
|
46
|
-
.replace(/([a-zA-Z])/, (str) => str.toUpperCase());
|
|
47
|
-
export const toKebabCase = (str) => str
|
|
48
|
-
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
49
|
-
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
50
|
-
.replace(/[\s_]+/g, '-')
|
|
51
|
-
.toLowerCase();
|
|
52
|
-
export function isTrackingRequestSent(trackingRequestUrl) {
|
|
53
|
-
// eslint-disable-next-line
|
|
54
|
-
const trackingRequestsQueue = window.localStorage?._constructorio_requests;
|
|
55
|
-
return (trackingRequestsQueue &&
|
|
56
|
-
JSON.parse(trackingRequestsQueue)?.some((request) => request?.url?.includes(trackingRequestUrl)));
|
|
57
|
-
}
|
|
58
8
|
export function clearConstructorRequests() {
|
|
59
9
|
// eslint-disable-next-line
|
|
60
10
|
if (window.localStorage?._constructorio_requests) {
|
|
@@ -96,22 +46,6 @@ export const functionStrings = {
|
|
|
96
46
|
</div>
|
|
97
47
|
)`,
|
|
98
48
|
};
|
|
99
|
-
export const stringifyWithDefaults = (obj) => {
|
|
100
|
-
// Stringify non-function values normally. Add a template block for functions to be replaced later
|
|
101
|
-
let res = JSON.stringify(obj, (key, value) => (value instanceof Function ? `${key}_CODE` : value), ' ');
|
|
102
|
-
// Replace template blocks with function strings
|
|
103
|
-
Array.from(res.matchAll(/"(\w*)_CODE"/g)).forEach((match) => {
|
|
104
|
-
const [codePlaceholder, key] = match;
|
|
105
|
-
const functionString = functionStrings[key];
|
|
106
|
-
if (functionString) {
|
|
107
|
-
res = res.replaceAll(codePlaceholder, functionString);
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
console.error(`Function string for ${key} not found.`); // eslint-disable-line
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
return res;
|
|
114
|
-
};
|
|
115
49
|
export const disableStoryActions = (story) => {
|
|
116
50
|
// eslint-disable-next-line
|
|
117
51
|
story.parameters.actions = { argTypesRegex: null };
|
|
@@ -174,25 +108,6 @@ export const getActiveSectionsWithData = (activeSections, sectionsResults, secti
|
|
|
174
108
|
return activeSectionsWithData;
|
|
175
109
|
};
|
|
176
110
|
export const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
177
|
-
export const trackRecommendationView = (target, activeSectionsWithData, cioClient) => {
|
|
178
|
-
if (target.dataset.cnstrcRecommendationsPodId) {
|
|
179
|
-
// Pull recommendations from activeSectionsWithData by podId surfaced on target
|
|
180
|
-
const recommendationSection = activeSectionsWithData.find((section) => isRecommendationsSection(section) &&
|
|
181
|
-
section.podId === target.dataset.cnstrcRecommendationsPodId);
|
|
182
|
-
const recommendationItems = recommendationSection?.data.map((item) => ({
|
|
183
|
-
itemId: item.data?.id,
|
|
184
|
-
itemName: item.value,
|
|
185
|
-
variationId: item.data?.variation_id,
|
|
186
|
-
}));
|
|
187
|
-
cioClient?.tracker.trackRecommendationView({
|
|
188
|
-
podId: target.dataset.cnstrcRecommendationsPodId,
|
|
189
|
-
numResultsViewed: recommendationItems?.length || 0,
|
|
190
|
-
url: window.location.href,
|
|
191
|
-
section: target.dataset.cnstrcSection,
|
|
192
|
-
items: recommendationItems,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
111
|
export const getItemsForActiveSections = (activeSectionsWithData) => {
|
|
197
112
|
const items = [];
|
|
198
113
|
activeSectionsWithData?.forEach((config) => {
|
|
@@ -211,18 +126,6 @@ export const translate = (word, translations) => {
|
|
|
211
126
|
return translations[word];
|
|
212
127
|
return localTranslations[word] || word;
|
|
213
128
|
};
|
|
214
|
-
export const trackSearchSubmit = (cioClient, term, autocompleteData = {}) => {
|
|
215
|
-
cioClient?.tracker.trackSearchSubmit(term, autocompleteData);
|
|
216
|
-
storageSetItem(CONSTANTS.SEARCH_TERM_STORAGE_KEY, term);
|
|
217
|
-
storeRecentSearch(term, {});
|
|
218
|
-
storeRecentAction(CONSTANTS.SEARCH_SUBMIT);
|
|
219
|
-
};
|
|
220
|
-
export const trackAutocompleteSelect = (cioClient, itemName, autocompleteData = {}) => {
|
|
221
|
-
cioClient?.tracker.trackAutocompleteSelect(itemName, autocompleteData);
|
|
222
|
-
if (autocompleteData?.section === 'Products') {
|
|
223
|
-
storageRemoveItem(CONSTANTS.SEARCH_TERM_STORAGE_KEY);
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
129
|
export const logger = (error) => {
|
|
227
130
|
try {
|
|
228
131
|
if (typeof process !== 'undefined' && process?.env?.LOGGER) {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { logger } from './helpers';
|
|
2
|
+
// Return storage engine based on scope
|
|
3
|
+
export const getStorageEngine = (scope) => {
|
|
4
|
+
if (scope === 'local') {
|
|
5
|
+
return localStorage;
|
|
6
|
+
}
|
|
7
|
+
return sessionStorage;
|
|
8
|
+
};
|
|
9
|
+
// Retrieves item from storage for key
|
|
10
|
+
export const storageGetItem = (key) => {
|
|
11
|
+
try {
|
|
12
|
+
const storageEngine = getStorageEngine(key.scope);
|
|
13
|
+
return storageEngine.getItem(key.key);
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
logger(`storageGetItem error: ${e}`);
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
// Retrieve array from storage
|
|
21
|
+
export const storageGetArray = (key) => {
|
|
22
|
+
const item = storageGetItem(key);
|
|
23
|
+
if (item) {
|
|
24
|
+
try {
|
|
25
|
+
const array = JSON.parse(item);
|
|
26
|
+
return array;
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
logger(`storageGetArray error: ${e}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
};
|
|
34
|
+
// Set item in storage
|
|
35
|
+
export const storageSetItem = (key, value) => {
|
|
36
|
+
try {
|
|
37
|
+
const storageEngine = getStorageEngine(key.scope);
|
|
38
|
+
return storageEngine.setItem(key.key, value);
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
logger(`storageSetItem error: ${e}`);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
// Remove item in storage
|
|
46
|
+
export const storageRemoveItem = (key) => {
|
|
47
|
+
try {
|
|
48
|
+
const storageEngine = getStorageEngine(key.scope);
|
|
49
|
+
return storageEngine.removeItem(key.key);
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
logger(`storageRemoveItem error: ${e}`);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { isRecommendationsSection } from '../typeGuards';
|
|
2
|
+
// eslint-disable-next-line import/no-cycle
|
|
3
|
+
import { CONSTANTS, storeRecentSearch, storeRecentAction } from './beaconUtils';
|
|
4
|
+
import { storageSetItem, storageRemoveItem } from './storage';
|
|
5
|
+
export function isTrackingRequestSent(trackingRequestUrl) {
|
|
6
|
+
// eslint-disable-next-line
|
|
7
|
+
const trackingRequestsQueue = window.localStorage?._constructorio_requests;
|
|
8
|
+
return (trackingRequestsQueue &&
|
|
9
|
+
JSON.parse(trackingRequestsQueue)?.some((request) => request?.url?.includes(trackingRequestUrl)));
|
|
10
|
+
}
|
|
11
|
+
export const trackRecommendationView = (target, activeSectionsWithData, cioClient) => {
|
|
12
|
+
if (target.dataset.cnstrcRecommendationsPodId) {
|
|
13
|
+
// Pull recommendations from activeSectionsWithData by podId surfaced on target
|
|
14
|
+
const recommendationSection = activeSectionsWithData.find((section) => isRecommendationsSection(section) &&
|
|
15
|
+
section.podId === target.dataset.cnstrcRecommendationsPodId);
|
|
16
|
+
const recommendationItems = recommendationSection?.data.map((item) => ({
|
|
17
|
+
itemId: item.data?.id,
|
|
18
|
+
itemName: item.value,
|
|
19
|
+
variationId: item.data?.variation_id,
|
|
20
|
+
}));
|
|
21
|
+
cioClient?.tracker.trackRecommendationView({
|
|
22
|
+
podId: target.dataset.cnstrcRecommendationsPodId,
|
|
23
|
+
numResultsViewed: recommendationItems?.length || 0,
|
|
24
|
+
url: window.location.href,
|
|
25
|
+
section: target.dataset.cnstrcSection,
|
|
26
|
+
items: recommendationItems,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export const trackSearchSubmit = (cioClient, term, autocompleteData = {}) => {
|
|
31
|
+
cioClient?.tracker.trackSearchSubmit(term, autocompleteData);
|
|
32
|
+
storageSetItem(CONSTANTS.SEARCH_TERM_STORAGE_KEY, term);
|
|
33
|
+
storeRecentSearch(term, {});
|
|
34
|
+
storeRecentAction(CONSTANTS.SEARCH_SUBMIT);
|
|
35
|
+
};
|
|
36
|
+
export const trackAutocompleteSelect = (cioClient, itemName, autocompleteData = {}) => {
|
|
37
|
+
cioClient?.tracker.trackAutocompleteSelect(itemName, autocompleteData);
|
|
38
|
+
if (autocompleteData?.section === 'Products') {
|
|
39
|
+
storageRemoveItem(CONSTANTS.SEARCH_TERM_STORAGE_KEY);
|
|
40
|
+
}
|
|
41
|
+
};
|
package/lib/mjs/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.23.
|
|
1
|
+
export default '1.23.29';
|
|
@@ -15,12 +15,7 @@ export declare const CONSTANTS: {
|
|
|
15
15
|
RECENT_SEARCHES_STORAGE_COUNT: number;
|
|
16
16
|
RECENT_ACTION_STORAGE_COUNT: number;
|
|
17
17
|
};
|
|
18
|
-
export declare const getStorageEngine: (scope: any) => Storage;
|
|
19
|
-
export declare const storageSetItem: (key: any, value: any) => void | null;
|
|
20
|
-
export declare const storageRemoveItem: (key: any) => void | null;
|
|
21
18
|
export declare const cleanTerm: (term: any) => string;
|
|
22
|
-
export declare const storageGetItem: (key: any) => string | null;
|
|
23
|
-
export declare const storageGetArray: (key: any) => any;
|
|
24
19
|
export declare const getRecentSearches: () => any;
|
|
25
20
|
export declare const storeRecentSearch: (term: any, suggestionData: any) => void;
|
|
26
21
|
export declare const getRecentActions: () => any;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AutocompleteRequestType } from '@constructor-io/constructorio-client-javascript';
|
|
2
|
+
declare const AUTOSUGGEST_CUSTOM_UI_VARIANTS: string[];
|
|
3
|
+
export type CustomAutosuggestUiVariant = (typeof AUTOSUGGEST_CUSTOM_UI_VARIANTS)[number];
|
|
4
|
+
export declare function getFeatures(request: Partial<AutocompleteRequestType>): {
|
|
5
|
+
featureDisplaySearchSuggestionImages: boolean;
|
|
6
|
+
featureDisplaySearchSuggestionResultCounts: boolean;
|
|
7
|
+
featureDisplayZeroStateRecommendations: boolean;
|
|
8
|
+
};
|
|
9
|
+
export {};
|