@constructor-io/constructorio-ui-autocomplete 1.15.1 → 1.16.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/dist/constructorio-ui-autocomplete-bundled.js +11 -11
- package/lib/cjs/components/Autocomplete/SectionItemsList/SectionItemsList.js +4 -2
- package/lib/cjs/constants.js +1 -0
- package/lib/cjs/hooks/useCioAutocomplete.js +25 -8
- package/lib/cjs/hooks/useDownShift.js +24 -8
- package/lib/cjs/hooks/useRecommendationsObserver.js +53 -0
- package/lib/cjs/hooks/useSections.js +10 -14
- package/lib/cjs/utils.js +48 -10
- package/lib/cjs/version.js +1 -1
- package/lib/mjs/components/Autocomplete/SectionItemsList/SectionItemsList.js +4 -2
- package/lib/mjs/constants.js +1 -0
- package/lib/mjs/hooks/useCioAutocomplete.js +26 -10
- package/lib/mjs/hooks/useDownShift.js +24 -8
- package/lib/mjs/hooks/useRecommendationsObserver.js +51 -0
- package/lib/mjs/hooks/useSections.js +11 -15
- package/lib/mjs/utils.js +45 -9
- package/lib/mjs/version.js +1 -1
- package/lib/types/components/Autocomplete/CioAutocompleteProvider.d.ts +1 -0
- package/lib/types/constants.d.ts +1 -1
- package/lib/types/hooks/useCioAutocomplete.d.ts +3 -2
- package/lib/types/hooks/useRecommendationsObserver.d.ts +17 -0
- package/lib/types/hooks/useSections.d.ts +2 -2
- package/lib/types/types.d.ts +4 -0
- package/lib/types/utils.d.ts +4 -2
- package/lib/types/version.d.ts +1 -1
- package/package.json +5 -3
- package/lib/cjs/hooks/useItems.js +0 -12
- package/lib/mjs/hooks/useItems.js +0 -10
- package/lib/types/hooks/useItems.d.ts +0 -3
package/lib/mjs/utils.js
CHANGED
|
@@ -107,25 +107,61 @@ export const getCioClient = (apiKey, cioJsClientOptions) => {
|
|
|
107
107
|
}
|
|
108
108
|
return null;
|
|
109
109
|
};
|
|
110
|
-
export const getActiveSectionsWithData = (activeSections, sectionResults) => {
|
|
110
|
+
export const getActiveSectionsWithData = (activeSections, sectionResults, sectionsRefs) => {
|
|
111
111
|
const activeSectionsWithData = [];
|
|
112
|
-
activeSections?.forEach((
|
|
113
|
-
const { identifier } =
|
|
114
|
-
let
|
|
115
|
-
if (isCustomSection(
|
|
112
|
+
activeSections?.forEach((sectionConfig, index) => {
|
|
113
|
+
const { identifier } = sectionConfig;
|
|
114
|
+
let sectionData;
|
|
115
|
+
if (isCustomSection(sectionConfig)) {
|
|
116
116
|
// Copy id from data to the top level
|
|
117
|
-
|
|
117
|
+
sectionData = sectionConfig.data.map((item) => ({
|
|
118
118
|
...item,
|
|
119
119
|
id: item?.id || item?.data?.id,
|
|
120
120
|
}));
|
|
121
121
|
}
|
|
122
122
|
else {
|
|
123
|
-
|
|
123
|
+
sectionData = sectionResults[identifier];
|
|
124
124
|
}
|
|
125
|
-
if (Array.isArray(
|
|
126
|
-
|
|
125
|
+
if (Array.isArray(sectionData)) {
|
|
126
|
+
const section = {
|
|
127
|
+
...sectionConfig,
|
|
128
|
+
data: sectionData,
|
|
129
|
+
};
|
|
130
|
+
// If ref passed as part of `SectionConfiguration`, use it.
|
|
131
|
+
// Otherwise, use the ref from our library generated refs array
|
|
132
|
+
const userDefinedSectionRef = sectionConfig.ref;
|
|
133
|
+
const libraryGeneratedSectionRef = sectionsRefs.current[index];
|
|
134
|
+
section.ref = userDefinedSectionRef || libraryGeneratedSectionRef;
|
|
135
|
+
activeSectionsWithData.push(section);
|
|
127
136
|
}
|
|
128
137
|
});
|
|
129
138
|
return activeSectionsWithData;
|
|
130
139
|
};
|
|
131
140
|
export const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
141
|
+
export const trackRecommendationView = (target, activeSectionsWithData, cioClient) => {
|
|
142
|
+
if (target.dataset.cnstrcRecommendationsPodId) {
|
|
143
|
+
// Pull recommendations from activeSectionsWithData by podId surfaced on target
|
|
144
|
+
const recommendationSection = activeSectionsWithData.find((section) => section.identifier === target.dataset.cnstrcRecommendationsPodId);
|
|
145
|
+
const recommendationItems = recommendationSection?.data.map((item) => ({
|
|
146
|
+
itemId: item.data?.id,
|
|
147
|
+
itemName: item.value,
|
|
148
|
+
variationId: item.data?.variation_id,
|
|
149
|
+
}));
|
|
150
|
+
cioClient?.tracker.trackRecommendationView({
|
|
151
|
+
podId: target.dataset.cnstrcRecommendationsPodId,
|
|
152
|
+
numResultsViewed: recommendationItems?.length || 0,
|
|
153
|
+
url: window.location.href,
|
|
154
|
+
section: target.dataset.cnstrcSection,
|
|
155
|
+
items: recommendationItems,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
export const getItemsForActiveSections = (activeSectionsWithData) => {
|
|
160
|
+
const items = [];
|
|
161
|
+
activeSectionsWithData?.forEach((config) => {
|
|
162
|
+
if (config?.data) {
|
|
163
|
+
items.push(...config.data);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
return items;
|
|
167
|
+
};
|
package/lib/mjs/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.
|
|
1
|
+
export default '1.16.1';
|
|
@@ -22,6 +22,7 @@ export declare const CioAutocompleteContext: React.Context<{
|
|
|
22
22
|
className: string;
|
|
23
23
|
'data-testid': string;
|
|
24
24
|
};
|
|
25
|
+
getSectionProps: (section: import("../../types").Section) => import("../../types").HTMLPropsWithCioDataAttributes<any>;
|
|
25
26
|
setQuery: React.Dispatch<React.SetStateAction<string>>;
|
|
26
27
|
cioClient: import("@constructor-io/constructorio-client-javascript/lib/types").Nullable<import("@constructor-io/constructorio-client-javascript")>;
|
|
27
28
|
autocompleteClassName: string;
|
package/lib/types/constants.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AutocompleteSubmitEvent } from './types';
|
|
2
2
|
export declare const apiKey = "key_M57QS8SMPdLdLx4x";
|
|
3
3
|
export declare const componentDescription = "- import `CioAutocomplete` to render in your JSX.\n- This component handles state management, data fetching, and rendering logic.\n- To use this component, an `apiKey` or `cioJsClient` are required, and an `onSubmit` callback must be passed. All other values are optional.\n- Use different props to configure the behavior of this component.\n- The following stories shows how different props affect the component's behavior\n\n> Note: when we say `cioJsClient`, we are referring to an instance of the [constructorio-client-javascript](https://www.npmjs.com/package/@constructor-io/constructorio-client-javascript)\n";
|
|
4
|
-
export declare const hookDescription = "- import `useCioAutocomplete` and call this custom hook in a functional component.\n- This hook leaves rendering logic up to you, while handling:\n - state management\n - data fetching\n - keyboard navigation\n - mouse interactions\n - focus and submit event handling\n- To use this hook, an `apiKey` or `cioJsClient` are required, and an `onSubmit` callback must be passed to the `useCioAutocomplete` hook to configure behavior. All other values are optional.\n- use the <a href=\"https://kentcdodds.com/blog/how-to-give-rendering-control-to-users-with-prop-getters\" target=\"__blank\">prop getters</a> and other variables returned by this hook (below) to leverage the functionality described above with jsx elements in your react component definitions\n\nCalling the `useCioAutocomplete` hook returns an object with the following keys:\n\n```jsx\nconst {\n // must be used for a hooks integrations\n query: string, // current input field value\n sections: [{...}], // array of sections data to render in menu list\n getFormProps: () => ({...})), // prop getter for jsx form element\n getInputProps: () => ({...})), // prop getter for jsx input element\n getMenuProps: () => ({...})), // prop getter for jsx element rendering the results container\n getItemProps: (item) => ({...})), // prop getter for jsx element rendering each result\n\n // available for use, but not required for all use cases\n selectedItem: item, // undefined or current selected item (via hover or arrow keys)\n isOpen: boolean, // current state of the menu list\n openMenu: () => void, // open menu\n closeMenu: () => void, // close menu\n setQuery: () => void, // update the current input field value\n getLabelProps: () => ({...})), // prop getter for a jsx label element\n cioJsClient, // instance of constructorio-client-javascript\n } = useCioAutocomplete(args);\n```\n\n> Note: when we say `cioJsClient`, we are referring to an instance of the [constructorio-client-javascript](https://www.npmjs.com/package/@constructor-io/constructorio-client-javascript)\n\nThe following stories show how different options affect the hook's behavior!\n";
|
|
4
|
+
export declare const hookDescription = "- import `useCioAutocomplete` and call this custom hook in a functional component.\n- This hook leaves rendering logic up to you, while handling:\n - state management\n - data fetching\n - keyboard navigation\n - mouse interactions\n - focus and submit event handling\n- To use this hook, an `apiKey` or `cioJsClient` are required, and an `onSubmit` callback must be passed to the `useCioAutocomplete` hook to configure behavior. All other values are optional.\n- use the <a href=\"https://kentcdodds.com/blog/how-to-give-rendering-control-to-users-with-prop-getters\" target=\"__blank\">prop getters</a> and other variables returned by this hook (below) to leverage the functionality described above with jsx elements in your react component definitions\n\nCalling the `useCioAutocomplete` hook returns an object with the following keys:\n\n```jsx\nconst {\n // must be used for a hooks integrations\n query: string, // current input field value\n sections: [{...}], // array of sections data to render in menu list\n getFormProps: () => ({...})), // prop getter for jsx form element\n getInputProps: () => ({...})), // prop getter for jsx input element\n getMenuProps: () => ({...})), // prop getter for jsx element rendering the results container\n getItemProps: (item) => ({...})), // prop getter for jsx element rendering each result\n getSectionProps: (section: Section) => ({...})), // prop getter for jsx element rendering each section.\n\n // available for use, but not required for all use cases\n selectedItem: item, // undefined or current selected item (via hover or arrow keys)\n isOpen: boolean, // current state of the menu list\n openMenu: () => void, // open menu\n closeMenu: () => void, // close menu\n setQuery: () => void, // update the current input field value\n getLabelProps: () => ({...})), // prop getter for a jsx label element\n cioJsClient, // instance of constructorio-client-javascript\n } = useCioAutocomplete(args);\n```\n\n> Note: when we say `cioJsClient`, we are referring to an instance of the [constructorio-client-javascript](https://www.npmjs.com/package/@constructor-io/constructorio-client-javascript)\n\nThe following stories show how different options affect the hook's behavior!\n";
|
|
5
5
|
export declare const sectionsDescription = "- by default, typing a query will fetch data for search suggestions and Products\n- to override this, pass an array of sections objects\n- the order of the objects in the `sections` array determines the order of the results\n- each section object must have an `identifier`\n- each section object can specify a `type`\n- each section object can override the default `numResults` of 8\n\nWhen no values are passed for the `sections` argument, the following defaults are used:\n\n```jsx\n[\n {\n identifier: 'Search Suggestions',\n type: 'autocomplete',\n numResults: 8\n },\n {\n identifier: 'Products',\n type: 'autocomplete',\n numResults: 8\n }\n]\n```\n";
|
|
6
6
|
export declare const userEventsDescription = "- pass callback functions to respond to user events\n- if provided, the onFocus callback function will be called each time the user focuses on the text input field\n- if provided, the onChange callback function will be called each time the user changes the value in the text input field\n- the onSubmit callback function will be called each time the user submits the form\n- the user can submit the form by pressing the enter key in the text input field, clicking a submit button within the form, clicking on a result, or pressing enter while a result is selected\n\n> \u26A0\uFE0F NOTE \u26A0\uFE0F Use the Storybook Canvas Actions tab to explore the behavior of all of these `OnEvent` callback functions as you interact with our Default User Events example rendered in the Canvas. In the stories below, Storybook Canvas Actions have been disabled to focus on each of these callback functions in isolation. Each of the example callback functions in the stories below log output to the console tab of the browser's developer tools.";
|
|
7
7
|
export declare const zeroStateDescription = "- when the text input field has no text, we call this zero state\n- by default, the autocomplete shows nothing in the menu it's for zero state\n- to show zero state results, pass an array of section objects for `zeroStateSections`\n- when `zeroStateSections` has sections, the menu will open on user focus by default\n- set `openOnFocus` to false, to only show `zeroStateSections` after user has typed and then cleared the text input, instead of as soon as the user focuses on the text input\n- the order of the objects in the `zeroStateSections` array determines the order of the results\n- each section object must have an `identifier`\n- each section object can specify a `type`\n- each section object can override the default `numResults` of 8";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { CioAutocompleteProps, UserDefinedSection } from '../types';
|
|
1
|
+
import { CioAutocompleteProps, Section, UserDefinedSection, HTMLPropsWithCioDataAttributes } from '../types';
|
|
2
2
|
export declare const defaultSections: UserDefinedSection[];
|
|
3
3
|
export type UseCioAutocompleteOptions = Omit<CioAutocompleteProps, 'children'>;
|
|
4
4
|
declare const useCioAutocomplete: (options: UseCioAutocompleteOptions) => {
|
|
5
5
|
query: string;
|
|
6
|
-
sections:
|
|
6
|
+
sections: Section[];
|
|
7
7
|
request: Partial<import("@constructor-io/constructorio-client-javascript/lib/types").AutocompleteRequestType>;
|
|
8
8
|
featureToggles: {
|
|
9
9
|
featureDisplaySearchSuggestionImages: boolean;
|
|
@@ -23,6 +23,7 @@ declare const useCioAutocomplete: (options: UseCioAutocompleteOptions) => {
|
|
|
23
23
|
className: string;
|
|
24
24
|
'data-testid': string;
|
|
25
25
|
};
|
|
26
|
+
getSectionProps: (section: Section) => HTMLPropsWithCioDataAttributes<any>;
|
|
26
27
|
setQuery: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
27
28
|
cioClient: import("@constructor-io/constructorio-client-javascript/lib/types").Nullable<import("@constructor-io/constructorio-client-javascript")>;
|
|
28
29
|
autocompleteClassName: string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Nullable } from '@constructor-io/constructorio-client-javascript/lib/types';
|
|
2
|
+
import ConstructorIO from '@constructor-io/constructorio-client-javascript';
|
|
3
|
+
import { Section } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Custom hook that observes the visibility of recommendation sections and calls trackRecommendationView event.
|
|
6
|
+
* This is done by using the IntersectionObserver API to observe the visibility of each recommendation section.
|
|
7
|
+
* That is done by passing the ref of each recommendation section to the IntersectionObserver.
|
|
8
|
+
* The refs are either passed as a prop in `SectionConfiguration` or created by the library by default.
|
|
9
|
+
* Either way the refs are stored in the sections array.
|
|
10
|
+
*
|
|
11
|
+
* @param menuIsOpen - A boolean indicating whether the menu is open.
|
|
12
|
+
* @param sections - An array of sections to observe.
|
|
13
|
+
* @param constructorIO - An instance of the ConstructorIO client.
|
|
14
|
+
* @param trackRecommendationView - A callback function to track the recommendation view event.
|
|
15
|
+
*/
|
|
16
|
+
declare function useRecommendationsObserver(menuIsOpen: boolean, sections: Section[], constructorIO: Nullable<ConstructorIO>, trackRecommendationView: (target: HTMLElement, sections: Section[], constructorIO: Nullable<ConstructorIO>) => void): void;
|
|
17
|
+
export default useRecommendationsObserver;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import ConstructorIO from '@constructor-io/constructorio-client-javascript';
|
|
2
2
|
import { Nullable } from '@constructor-io/constructorio-client-javascript/lib/types';
|
|
3
|
-
import { AdvancedParameters, UserDefinedSection } from '../types';
|
|
3
|
+
import { AdvancedParameters, Section, UserDefinedSection } from '../types';
|
|
4
4
|
export default function useSections(query: string, cioClient: Nullable<ConstructorIO>, sections: UserDefinedSection[], zeroStateSections: UserDefinedSection[] | undefined, advancedParameters?: AdvancedParameters): {
|
|
5
5
|
activeSections: UserDefinedSection[];
|
|
6
|
-
activeSectionsWithData:
|
|
6
|
+
activeSectionsWithData: Section[];
|
|
7
7
|
zeroStateActiveSections: false | UserDefinedSection[] | undefined;
|
|
8
8
|
request: Partial<import("@constructor-io/constructorio-client-javascript/lib/types").AutocompleteRequestType>;
|
|
9
9
|
};
|
package/lib/types/types.d.ts
CHANGED
|
@@ -63,6 +63,7 @@ export type SectionConfiguration = {
|
|
|
63
63
|
displayName?: string;
|
|
64
64
|
numResults?: number;
|
|
65
65
|
displaySearchTermHighlights?: boolean;
|
|
66
|
+
ref?: React.RefObject<HTMLElement>;
|
|
66
67
|
};
|
|
67
68
|
export interface AutocompleteSection extends SectionConfiguration {
|
|
68
69
|
type?: 'autocomplete';
|
|
@@ -91,3 +92,6 @@ export type InGroupSuggestion = SearchSuggestion & {
|
|
|
91
92
|
groupId: string;
|
|
92
93
|
groupName: string;
|
|
93
94
|
};
|
|
95
|
+
export type HTMLPropsWithCioDataAttributes<T = any> = React.DetailedHTMLProps<React.HTMLAttributes<T>, T> & {
|
|
96
|
+
[key: `data-cnstrc-${string}`]: any;
|
|
97
|
+
};
|
package/lib/types/utils.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ConstructorIOClient from '@constructor-io/constructorio-client-javascript';
|
|
2
|
-
import { AutocompleteRequestType, ConstructorClientOptions } from '@constructor-io/constructorio-client-javascript/lib/types';
|
|
2
|
+
import { AutocompleteRequestType, Nullable, ConstructorClientOptions } from '@constructor-io/constructorio-client-javascript/lib/types';
|
|
3
3
|
import { OnSubmit, Item, Section, UserDefinedSection, SectionsData } from './types';
|
|
4
4
|
export type GetItemPosition = (args: {
|
|
5
5
|
item: Item;
|
|
@@ -37,6 +37,8 @@ export declare const stringifyWithDefaults: (obj: {
|
|
|
37
37
|
}) => string;
|
|
38
38
|
export declare const disableStoryActions: (story: any) => void;
|
|
39
39
|
export declare const getCioClient: (apiKey?: string, cioJsClientOptions?: ConstructorClientOptions) => ConstructorIOClient | null;
|
|
40
|
-
export declare const getActiveSectionsWithData: (activeSections: UserDefinedSection[], sectionResults: SectionsData) => Section[];
|
|
40
|
+
export declare const getActiveSectionsWithData: (activeSections: UserDefinedSection[], sectionResults: SectionsData, sectionsRefs: React.MutableRefObject<React.RefObject<HTMLLIElement>[]>) => Section[];
|
|
41
41
|
export declare const escapeRegExp: (string: string) => string;
|
|
42
|
+
export declare const trackRecommendationView: (target: HTMLElement, activeSectionsWithData: Section[], cioClient: Nullable<ConstructorIOClient>) => void;
|
|
43
|
+
export declare const getItemsForActiveSections: (activeSectionsWithData: Section[]) => Item[];
|
|
42
44
|
export {};
|
package/lib/types/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "1.
|
|
1
|
+
declare const _default: "1.16.1";
|
|
2
2
|
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructor-io/constructorio-ui-autocomplete",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.1",
|
|
4
4
|
"description": "Constructor.io Autocomplete UI library for web applications",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/mjs/index.js",
|
|
@@ -11,11 +11,13 @@
|
|
|
11
11
|
},
|
|
12
12
|
".": {
|
|
13
13
|
"import": "./lib/mjs/index.js",
|
|
14
|
-
"require": "./lib/cjs/index.js"
|
|
14
|
+
"require": "./lib/cjs/index.js",
|
|
15
|
+
"types": "./lib/types/index.d.ts"
|
|
15
16
|
},
|
|
16
17
|
"./cjs": {
|
|
17
18
|
"import": "./lib/cjs/index.js",
|
|
18
|
-
"require": "./lib/cjs/index.js"
|
|
19
|
+
"require": "./lib/cjs/index.js",
|
|
20
|
+
"types": "./lib/types/index.d.ts"
|
|
19
21
|
},
|
|
20
22
|
"./constructorio-ui-autocomplete-bundled": {
|
|
21
23
|
"import": "./dist/constructorio-ui-autocomplete-bundled.js",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const useItems = (activeSectionsWithData) => {
|
|
4
|
-
const items = [];
|
|
5
|
-
activeSectionsWithData === null || activeSectionsWithData === void 0 ? void 0 : activeSectionsWithData.forEach((config) => {
|
|
6
|
-
if (config === null || config === void 0 ? void 0 : config.data) {
|
|
7
|
-
items.push(...config.data);
|
|
8
|
-
}
|
|
9
|
-
});
|
|
10
|
-
return items;
|
|
11
|
-
};
|
|
12
|
-
exports.default = useItems;
|