@constructor-io/constructorio-ui-plp 1.6.3 → 1.6.5

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.
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable jsx-a11y/click-events-have-key-events */
2
2
  import React from 'react';
3
3
  import { useCioPlpContext } from '../../hooks/useCioPlpContext';
4
- import { isHexColor } from '../../utils';
4
+ import { isHexColor, cnstrcDataAttrs } from '../../utils';
5
5
  export default function ProductSwatch(props) {
6
6
  const context = useCioPlpContext();
7
7
  const { swatchObject, children } = props;
@@ -31,8 +31,11 @@ export default function ProductSwatch(props) {
31
31
  const color = isHexColor(swatch?.swatchPreview)
32
32
  ? swatch?.swatchPreview
33
33
  : `url(${swatch?.swatchPreview})`;
34
- return (React.createElement("button", { type: 'button', key: swatch.variationId, "data-cnstrc-variation-id": swatch.variationId, "data-testid": `cio-swatch-${swatch.variationId}`, className: 'cio-swatch-button cio-swatch-item', onClick: (e) => swatchClickHandler(e, swatch), style: {
34
+ const variationIdAttr = {
35
+ [cnstrcDataAttrs.common.variationId]: swatch.variationId,
36
+ };
37
+ return (React.createElement("button", { type: 'button', key: swatch.variationId, "data-testid": `cio-swatch-${swatch.variationId}`, className: 'cio-swatch-button cio-swatch-item', onClick: (e) => swatchClickHandler(e, swatch), style: {
35
38
  background: color,
36
- } }, isSelected && (React.createElement("div", { "data-cnstrc-variation-id": swatch.variationId, className: 'cio-swatch-selected', style: { outline: `3px solid ${color}` } }))));
39
+ }, ...variationIdAttr }, isSelected && (React.createElement("div", { className: 'cio-swatch-selected', style: { outline: `3px solid ${color}` }, ...variationIdAttr }))));
37
40
  }))))));
38
41
  }
@@ -1,4 +1,3 @@
1
- // eslint-disable-next-line import/prefer-default-export
2
1
  export const DEMO_API_KEY = 'key_M57QS8SMPdLdLx4x';
3
2
  export const EMITTED_EVENTS = {
4
3
  PRODUCT_CARD_IMAGE_ROLLOVER: 'cio.ui-plp.productCardImageRollover',
@@ -65,14 +65,15 @@ export default function useCioPlp(props = {}) {
65
65
  const pagination = usePagination({ totalNumResults, ...paginationConfigs });
66
66
  const groups = useGroups({ groups: rawGroups, ...groupsConfigs });
67
67
  const data = isSearchPage ? search.data : browse.data;
68
- const plpContainerCnstrcDataAttributes = getPlpContainerCnstrcDataAttributes(data, requestConfigs);
68
+ const status = isSearchPage ? search.status : browse.status;
69
+ const plpContainerCnstrcDataAttributes = getPlpContainerCnstrcDataAttributes(data, requestConfigs, status === 'fetching');
69
70
  return {
70
71
  isSearchPage,
71
72
  isBrowsePage,
72
73
  searchQuery: search.query,
73
74
  browseFilterName: browse.filterName,
74
75
  browseFilterValue: browse.filterValue,
75
- status: isSearchPage ? search.status : browse.status,
76
+ status,
76
77
  data,
77
78
  refetch,
78
79
  filters,
@@ -1,38 +1,79 @@
1
1
  import { isPlpBrowseDataResults, isPlpSearchDataResults } from './typeHelpers';
2
2
  import { getPageType } from './requestConfigsHelpers';
3
- export function getProductCardCnstrcDataAttributes(productInfo) {
4
- let dataCnstrc = {};
3
+ export const cnstrcDataAttrs = {
4
+ common: {
5
+ itemId: 'data-cnstrc-item-id',
6
+ itemName: 'data-cnstrc-item-name',
7
+ itemPrice: 'data-cnstrc-item-price',
8
+ variationId: 'data-cnstrc-item-variation-id',
9
+ numResults: 'data-cnstrc-num-results',
10
+ conversionBtn: 'data-cnstrc-btn',
11
+ resultId: 'data-cnstrc-result-id',
12
+ section: 'data-cnstrc-section',
13
+ zeroResults: 'data-cnstrc-zero-result',
14
+ slCampaignId: 'data-cnstrc-sl-campaign-id',
15
+ slCampaignOwner: 'data-cnstrc-sl-campaign-owner',
16
+ },
17
+ search: {
18
+ searchContainer: 'data-cnstrc-search',
19
+ searchTerm: 'data-cnstrc-search-term',
20
+ },
21
+ browse: {
22
+ browseContainer: 'data-cnstrc-browse',
23
+ filterName: 'data-cnstrc-filter-name',
24
+ filterValue: 'data-cnstrc-filter-value',
25
+ },
26
+ };
27
+ export function getProductCardCnstrcDataAttributes(productInfo, options) {
5
28
  const { itemId, itemPrice, itemName, variationId } = productInfo;
6
- dataCnstrc = {
7
- 'data-cnstrc-item-id': itemId,
8
- 'data-cnstrc-item-name': itemName,
9
- 'data-cnstrc-item-price': itemPrice,
10
- 'data-cnstrc-item-variation-id': variationId,
29
+ const dataCnstrc = {
30
+ [cnstrcDataAttrs.common.itemId]: itemId,
31
+ [cnstrcDataAttrs.common.itemName]: itemName,
11
32
  };
33
+ // Only include variation ID if it exists
34
+ if (variationId) {
35
+ dataCnstrc[cnstrcDataAttrs.common.variationId] = variationId;
36
+ }
37
+ // Only include price if it exists
38
+ if (itemPrice !== undefined && itemPrice !== null) {
39
+ dataCnstrc[cnstrcDataAttrs.common.itemPrice] = itemPrice;
40
+ }
41
+ // Add sponsored listing data if available
42
+ if (options?.labels?.sl_campaign_id) {
43
+ dataCnstrc[cnstrcDataAttrs.common.slCampaignId] = String(options.labels.sl_campaign_id);
44
+ }
45
+ if (options?.labels?.sl_campaign_owner) {
46
+ dataCnstrc[cnstrcDataAttrs.common.slCampaignOwner] = String(options.labels.sl_campaign_owner);
47
+ }
12
48
  return dataCnstrc;
13
49
  }
14
- export function getPlpContainerCnstrcDataAttributes(data, requestConfigs) {
50
+ export function getPlpContainerCnstrcDataAttributes(data, requestConfigs, isLoading = false) {
15
51
  if (!data || (!isPlpSearchDataResults(data) && !isPlpBrowseDataResults(data)))
16
52
  return {};
17
53
  const { filterName, filterValue } = requestConfigs;
18
54
  const pageType = getPageType(requestConfigs);
55
+ const isZeroResults = data.response.totalNumResults === 0;
19
56
  let dataCnstrc = {};
20
57
  switch (pageType) {
21
58
  case 'browse':
22
59
  dataCnstrc = {
23
- 'data-cnstrc-browse': true,
24
- 'data-cnstrc-num-results': data.response.totalNumResults,
25
- 'data-cnstrc-result-id': data.resultId,
26
- 'data-cnstrc-filter-name': filterName,
27
- 'data-cnstrc-filter-value': filterValue,
60
+ [cnstrcDataAttrs.browse.browseContainer]: true,
61
+ [cnstrcDataAttrs.common.numResults]: data.response.totalNumResults,
62
+ [cnstrcDataAttrs.common.resultId]: data.resultId,
63
+ [cnstrcDataAttrs.browse.filterName]: filterName,
64
+ [cnstrcDataAttrs.browse.filterValue]: filterValue,
28
65
  };
29
66
  break;
30
67
  case 'search':
31
68
  dataCnstrc = {
32
- 'data-cnstrc-search': true,
33
- 'data-cnstrc-result-id': data.resultId,
34
- 'data-cnstrc-num-results': data.response.totalNumResults,
69
+ [cnstrcDataAttrs.search.searchContainer]: true,
70
+ [cnstrcDataAttrs.common.resultId]: data.resultId,
71
+ [cnstrcDataAttrs.common.numResults]: data.response.totalNumResults,
35
72
  };
73
+ // Add search term
74
+ if (data.request?.term) {
75
+ dataCnstrc[cnstrcDataAttrs.search.searchTerm] = data.request.term;
76
+ }
36
77
  break;
37
78
  case 'unknown':
38
79
  dataCnstrc = {};
@@ -40,5 +81,21 @@ export function getPlpContainerCnstrcDataAttributes(data, requestConfigs) {
40
81
  default:
41
82
  break;
42
83
  }
84
+ // Add common conditional attributes (applies to both search and browse)
85
+ if (pageType === 'search' || pageType === 'browse') {
86
+ // Add zero-result attribute only if not loading and there are no results
87
+ if (isZeroResults && !isLoading) {
88
+ dataCnstrc[cnstrcDataAttrs.common.zeroResults] = true;
89
+ }
90
+ // Add section if it's not "Products"
91
+ if (data.request?.section && data.request.section !== 'Products') {
92
+ dataCnstrc[cnstrcDataAttrs.common.section] = data.request.section;
93
+ }
94
+ }
43
95
  return dataCnstrc;
44
96
  }
97
+ export function getConversionButtonCnstrcDataAttributes(conversionType) {
98
+ return {
99
+ [cnstrcDataAttrs.common.conversionBtn]: conversionType,
100
+ };
101
+ }
@@ -1 +1 @@
1
- export default '1.6.3';
1
+ export default '1.6.5';
@@ -59,5 +59,5 @@ export default function useCioPlp(props?: UseCioPlpProps): {
59
59
  optionsToRender: PlpItemGroup[];
60
60
  setOptionsToRender: import("react").Dispatch<import("react").SetStateAction<PlpItemGroup[]>>;
61
61
  };
62
- plpContainerCnstrcDataAttributes: Record<`data-cnstrc-${string}`, string | number | boolean>;
62
+ plpContainerCnstrcDataAttributes: import("../types").CnstrcDataAttrs;
63
63
  };
@@ -75,7 +75,7 @@ export interface ProductCardRenderProps extends ProductCardProps {
75
75
  /**
76
76
  * Data Attributes to surface on parent div of product card.
77
77
  */
78
- productCardCnstrcDataAttributes: CnstrcData;
78
+ productCardCnstrcDataAttributes: CnstrcDataAttrs;
79
79
  }
80
80
  export type ProductCardProps = IncludeRenderProps<ProductCardBaseProps, ProductCardRenderProps>;
81
81
  export interface RenderOverrides {
@@ -295,7 +295,7 @@ export interface PlpItemGroup {
295
295
  children: Array<PlpItemGroup>;
296
296
  parents: Pick<PlpItemGroup, 'groupId' | 'displayName'>[];
297
297
  }
298
- export type CnstrcData = Record<`data-cnstrc-${string}`, string | number | boolean>;
298
+ export type CnstrcDataAttrs = Record<`data-cnstrc-${string}` | string, string | number | boolean>;
299
299
  export type PropsWithChildren<P> = P & {
300
300
  children?: ReactNode;
301
301
  };
@@ -1,3 +1,37 @@
1
- import { RequestConfigs, PlpSearchDataResults, PlpSearchDataRedirect, PlpBrowseData, CnstrcData, ProductInfoObject } from '../types';
2
- export declare function getProductCardCnstrcDataAttributes(productInfo: ProductInfoObject): CnstrcData;
3
- export declare function getPlpContainerCnstrcDataAttributes(data: PlpSearchDataResults | PlpSearchDataRedirect | PlpBrowseData | null, requestConfigs: RequestConfigs): Record<`data-cnstrc-${string}`, string | number | boolean>;
1
+ import { RequestConfigs, PlpSearchDataResults, PlpSearchDataRedirect, PlpBrowseData, CnstrcDataAttrs, ProductInfoObject } from '../types';
2
+ export interface ProductCardDataAttributeOptions {
3
+ labels?: {
4
+ sl_campaign_id?: string | number;
5
+ sl_campaign_owner?: string | number;
6
+ };
7
+ }
8
+ export declare const cnstrcDataAttrs: {
9
+ common: {
10
+ itemId: string;
11
+ itemName: string;
12
+ itemPrice: string;
13
+ variationId: string;
14
+ numResults: string;
15
+ conversionBtn: string;
16
+ resultId: string;
17
+ section: string;
18
+ zeroResults: string;
19
+ slCampaignId: string;
20
+ slCampaignOwner: string;
21
+ };
22
+ search: {
23
+ searchContainer: string;
24
+ searchTerm: string;
25
+ };
26
+ browse: {
27
+ browseContainer: string;
28
+ filterName: string;
29
+ filterValue: string;
30
+ };
31
+ };
32
+ export declare function getProductCardCnstrcDataAttributes(productInfo: ProductInfoObject, options?: ProductCardDataAttributeOptions): CnstrcDataAttrs;
33
+ export declare function getPlpContainerCnstrcDataAttributes(data: PlpSearchDataResults | PlpSearchDataRedirect | PlpBrowseData | null, requestConfigs: RequestConfigs, isLoading?: boolean): CnstrcDataAttrs;
34
+ export type ConversionType = 'add_to_cart' | 'add_to_wishlist' | 'like' | 'message' | 'make_offer' | 'read' | string;
35
+ export declare function getConversionButtonCnstrcDataAttributes(conversionType: ConversionType): {
36
+ [x: string]: string;
37
+ };
@@ -1,2 +1,2 @@
1
- declare const _default: "1.6.3";
1
+ declare const _default: "1.6.5";
2
2
  export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructor-io/constructorio-ui-plp",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
4
4
  "description": "Constructor PLP UI library for web applications",
5
5
  "author": "Constructor.io Corporation",
6
6
  "license": "MIT",