@envive-ai/react-toolkit 0.1.5 → 0.1.6

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.
Files changed (146) hide show
  1. package/dist/Accordion/index.cjs +84 -0
  2. package/dist/Accordion/index.d.cts +13 -0
  3. package/dist/Accordion/index.d.ts +13 -0
  4. package/dist/Accordion/index.js +77 -0
  5. package/dist/ButtonBase/index.cjs +2 -1
  6. package/dist/ButtonBase/index.d.cts +2 -2
  7. package/dist/ButtonBase/index.d.ts +3 -3
  8. package/dist/ButtonBase/index.js +2 -1
  9. package/dist/{ButtonBase-CpmFsiUf.js → ButtonBase-BIAu5fIG.js} +1 -1
  10. package/dist/ButtonBase-BRfuPPzN.js +1 -0
  11. package/dist/ButtonBase-BleAVeo-.cjs +0 -0
  12. package/dist/{ButtonBase-Dlh3bpR3.cjs → ButtonBase-DcyxOe2v.cjs} +2 -2
  13. package/dist/FilterScrollbar/index.cjs +1 -1
  14. package/dist/FilterScrollbar/index.d.cts +3 -3
  15. package/dist/FilterScrollbar/index.d.ts +4 -4
  16. package/dist/FilterScrollbar/index.js +1 -1
  17. package/dist/Headline/index.cjs +1 -1
  18. package/dist/Headline/index.d.cts +2 -2
  19. package/dist/Headline/index.d.ts +2 -2
  20. package/dist/Headline/index.js +1 -1
  21. package/dist/ImageWithFallback/index.cjs +1 -1
  22. package/dist/ImageWithFallback/index.d.cts +2 -2
  23. package/dist/ImageWithFallback/index.d.ts +2 -2
  24. package/dist/ImageWithFallback/index.js +1 -1
  25. package/dist/{ImageWithFallback-By6QdlCR.cjs → ImageWithFallback-1LqhQK1q.cjs} +2 -2
  26. package/dist/{ImageWithFallback-DtUrq_bk.js → ImageWithFallback-Ckwsmd8P.js} +1 -1
  27. package/dist/ProductCard/index.cjs +7 -8
  28. package/dist/ProductCard/index.d.cts +2 -108
  29. package/dist/ProductCard/index.d.ts +2 -108
  30. package/dist/ProductCard/index.js +4 -5
  31. package/dist/{ProductCard-CvTRvhm7.cjs → ProductCard-DZZKutY-.cjs} +64 -5
  32. package/dist/{ProductCard-aJbQz6Q7.js → ProductCard-SF8-lXlT.js} +46 -6
  33. package/dist/ProductGrid/index.cjs +5 -5
  34. package/dist/ProductGrid/index.d.cts +6 -6
  35. package/dist/ProductGrid/index.d.ts +6 -6
  36. package/dist/ProductGrid/index.js +5 -5
  37. package/dist/{ProductGrid-CSIH2_G9.cjs → ProductGrid-BSSmPr7K.cjs} +48 -46
  38. package/dist/{ProductGrid-NOCayW9O.js → ProductGrid-DTUhH219.js} +48 -46
  39. package/dist/{SearchInputAutocomplete → SearchAutocomplete}/index.cjs +1 -1
  40. package/dist/{SearchInputAutocomplete → SearchAutocomplete}/index.d.cts +1 -1
  41. package/dist/{SearchInputAutocomplete → SearchAutocomplete}/index.d.ts +1 -1
  42. package/dist/SearchAutocomplete/index.js +3 -0
  43. package/dist/{SearchAutocomplete-DCu9-Yfk.js → SearchAutocomplete-BPjlo6qq.js} +4 -4
  44. package/dist/{SearchAutocomplete-CQxxe5Op.cjs → SearchAutocomplete-BzaEXmRQ.cjs} +8 -8
  45. package/dist/SearchFilter/index.cjs +5 -5
  46. package/dist/SearchFilter/index.d.cts +1 -34
  47. package/dist/SearchFilter/index.d.ts +1 -34
  48. package/dist/SearchFilter/index.js +2 -2
  49. package/dist/{SearchFilterHeader-qkRVfAB5.cjs → SearchFilter-B15tybnV.cjs} +1 -1
  50. package/dist/{SearchFilterHeader-BDEcDc_4.js → SearchFilter-D427M2UE.js} +1 -1
  51. package/dist/SearchInput/index.cjs +3 -3
  52. package/dist/SearchInput/index.d.cts +3 -3
  53. package/dist/SearchInput/index.d.ts +3 -3
  54. package/dist/SearchInput/index.js +3 -3
  55. package/dist/{SearchInput-DxGvYGZO.js → SearchInput-C0wB4hSV.js} +6 -6
  56. package/dist/{SearchInput-Cdpwswyv.cjs → SearchInput-D6UW79wT.cjs} +10 -10
  57. package/dist/SearchInputForm/index.cjs +6 -5
  58. package/dist/SearchInputForm/index.d.cts +1 -31
  59. package/dist/SearchInputForm/index.d.ts +1 -31
  60. package/dist/SearchInputForm/index.js +6 -5
  61. package/dist/SearchResultsFilterSidebar/index.cjs +10 -6
  62. package/dist/SearchResultsFilterSidebar/index.d.cts +3 -44
  63. package/dist/SearchResultsFilterSidebar/index.d.ts +3 -44
  64. package/dist/SearchResultsFilterSidebar/index.js +7 -4
  65. package/dist/SearchResultsStates/index.cjs +23 -24
  66. package/dist/SearchResultsStates/index.d.cts +13 -6
  67. package/dist/SearchResultsStates/index.d.ts +14 -7
  68. package/dist/SearchResultsStates/index.js +19 -21
  69. package/dist/SparkleAnimation/index.cjs +1 -1
  70. package/dist/SparkleAnimation/index.d.cts +2 -2
  71. package/dist/SparkleAnimation/index.d.ts +2 -2
  72. package/dist/SparkleAnimation/index.js +1 -1
  73. package/dist/{SparkleAnimation-DfMCtvAQ.js → SparkleAnimation-BdOjC8l-.js} +2 -2
  74. package/dist/{SparkleAnimation-j-mAMEZZ.cjs → SparkleAnimation-BhyeL26m.cjs} +4 -4
  75. package/dist/Spinner/index.cjs +1 -1
  76. package/dist/Spinner/index.d.cts +2 -2
  77. package/dist/Spinner/index.d.ts +2 -2
  78. package/dist/Spinner/index.js +1 -1
  79. package/dist/SuggestionButton/index.cjs +3 -3
  80. package/dist/SuggestionButton/index.d.cts +2 -2
  81. package/dist/SuggestionButton/index.d.ts +3 -3
  82. package/dist/SuggestionButton/index.js +2 -2
  83. package/dist/Text/index.cjs +2 -10
  84. package/dist/Text/index.d.cts +3 -3
  85. package/dist/Text/index.d.ts +3 -3
  86. package/dist/Text/index.js +1 -9
  87. package/dist/Text-CV9pv8ds.js +10 -0
  88. package/dist/Text-DDT3sqY1.cjs +16 -0
  89. package/dist/TextInput/index.cjs +1 -1
  90. package/dist/TextInput/index.d.cts +1 -1
  91. package/dist/TextInput/index.d.ts +1 -1
  92. package/dist/TextInput/index.js +1 -1
  93. package/dist/{TextInput-CObd_Wcw.cjs → TextInput-C6fF9cSB.cjs} +2 -2
  94. package/dist/{TextInput-ChPhL54o.js → TextInput-CRMqBW3X.js} +1 -1
  95. package/dist/index-B0oln9VD.d.ts +58 -0
  96. package/dist/index-B125udRj.d.cts +78 -0
  97. package/dist/index-BHNzU-Pc.d.ts +36 -0
  98. package/dist/index-BNCrvswP.d.cts +36 -0
  99. package/dist/index-CQlBDGTL.d.cts +58 -0
  100. package/dist/{types-B7hf-Lif.d.ts → index-CcnuEYQN.d.ts} +110 -3
  101. package/dist/index-DMXTg_9L.d.ts +78 -0
  102. package/dist/{types-Dvgr3ZeV.d.cts → index-wYn2mEDm.d.cts} +110 -3
  103. package/dist/{searchFilterSidebarVariants-C_UTEIpZ.js → searchFilterSidebarVariants-BWQyiKwS.js} +1 -1
  104. package/dist/{searchFilterSidebarVariants-DcQLi_TT.cjs → searchFilterSidebarVariants-D08jyA7U.cjs} +1 -1
  105. package/package.json +10 -5
  106. package/src/components/Accordion/Accordion.tsx +90 -0
  107. package/src/components/Accordion/index.ts +1 -0
  108. package/src/components/AppliedFiltersScrollbar/AppliedFiltersScrollbar.tsx +70 -0
  109. package/src/components/DynamicFiltersScrollbar/DynamicFiltersScrollbar.tsx +52 -0
  110. package/src/components/ProductCard/ProductCard.tsx +34 -17
  111. package/src/components/ProductCard/types.ts +1 -1
  112. package/src/components/ProductGrid/ProductGrid.tsx +33 -33
  113. package/src/components/{SearchInputAutocomplete → SearchAutocomplete}/SearchAutocomplete.tsx +1 -1
  114. package/src/components/SearchInput/SearchInput.tsx +6 -6
  115. package/src/components/SearchInput/searchInputVariants.ts +5 -5
  116. package/src/components/SearchInputForm/SearchInputForm.tsx +6 -4
  117. package/src/components/SearchResultsContent/SearchResultsContent.tsx +87 -0
  118. package/src/components/SearchResultsContent/utils.ts +28 -0
  119. package/src/components/SearchResultsFilterSidebar/SearchResultsFilter.tsx +5 -6
  120. package/src/components/SearchResultsFilterSidebar/types.ts +14 -1
  121. package/src/components/SearchResultsStates/NoSearchResultsFound.tsx +2 -2
  122. package/src/components/SearchResultsStates/SearchResultsGrid.tsx +14 -12
  123. package/src/components/SearchResultsStates/SearchResultsLoadingGrid.tsx +4 -5
  124. package/dist/ProductCardSkeleton-B6YetUCT.js +0 -43
  125. package/dist/ProductCardSkeleton-BzBK36m-.cjs +0 -63
  126. package/dist/SearchInputAutocomplete/index.js +0 -3
  127. package/dist/types-5luH4G-3.d.cts +0 -5
  128. package/dist/types-BCAU5OQD.d.cts +0 -46
  129. package/dist/types-BIPqyTOJ.d.ts +0 -5
  130. package/dist/types-BwPquD10.d.ts +0 -46
  131. package/dist/types-CosVh8Hj.d.cts +0 -4
  132. package/dist/types-nR3jHgIO.d.ts +0 -4
  133. package/src/types/external.ts +0 -24
  134. /package/dist/{DynamicFiltersScrollbar-D8Lms7Ox.cjs → DynamicFiltersScrollbar-BTopFhyl.cjs} +0 -0
  135. /package/dist/{DynamicFiltersScrollbar-t_JASmYC.js → DynamicFiltersScrollbar-BmPTqym5.js} +0 -0
  136. /package/dist/{Headline-COAnonc2.js → Headline-XpaAeTSR.js} +0 -0
  137. /package/dist/{Headline-CdddUGwy.cjs → Headline-iP_MckEO.cjs} +0 -0
  138. /package/dist/{Spinner-D9kkaM9d.js → Spinner-BgGihEfJ.js} +0 -0
  139. /package/dist/{Spinner-DX35Epv3.cjs → Spinner-DzdIkS6t.cjs} +0 -0
  140. /package/dist/{colorsConfig-CKiMYHO_.js → colorsConfig-BQlaCfxi.js} +0 -0
  141. /package/dist/{colorsConfig-DulwYRIk.cjs → colorsConfig-DCvy_dV4.cjs} +0 -0
  142. /package/dist/{textVariantClasses-DwnnFNBf.d.cts → textVariantClasses-C8OCWZAw.d.ts} +0 -0
  143. /package/dist/{textVariantClasses-sT9E8Uty.d.ts → textVariantClasses-Cdg-UUHi.d.cts} +0 -0
  144. /package/dist/{types-B19i3fxM.d.ts → types-Bm-qQyO3.d.ts} +0 -0
  145. /package/dist/{types-DpfHwTzY.d.ts → types-BruEHw-X.d.ts} +0 -0
  146. /package/src/components/{SearchInputAutocomplete → SearchAutocomplete}/index.ts +0 -0
@@ -1,3 +1,30 @@
1
+ import { TestProps } from "./types-BQYpWDJ4.cjs";
2
+ import * as react_jsx_runtime17 from "react/jsx-runtime";
3
+ import { FC } from "react";
4
+
5
+ //#region src/config/chatElementDisplayLocation.d.ts
6
+ declare enum ChatElementDisplayLocation {
7
+ IN_CHAT = "in_chat",
8
+ CHAT_PREVIEW = "chat_preview",
9
+ FLOATING_BUTTON = "floating_button",
10
+ HELP_ME_CHOOSE = "help_me_choose",
11
+ PLP_IMAGE_BANNER = "plp_image_banner",
12
+ TOP_REVIEWS_SNIPPET = "top_reviews_snippet",
13
+ BOTTOM_REVIEWS_SNIPPET = "bottom_reviews_snippet",
14
+ BLOCK_BACK_BUTTON = "block_back_button",
15
+ SWITCH_TO_AGENT = "switch_to_agent",
16
+ CONVERSATIONAL_SEARCH = "conversational_search",
17
+ GLOBAL_SEARCH_ENTRYPOINT = "global_search_entrypoint",
18
+ SEARCH_NAV_ENTRYPOINT = "search_nav_entrypoint",
19
+ SEARCH_PROMPT = "search_prompt",
20
+ SEARCH_PROMPT_BUTTON = "search_prompt_button",
21
+ PRODUCT_GRID = "product_grid",
22
+ UNSPECIFIED = "unspecified",
23
+ FILTER_MODAL = "filter_modal",
24
+ PROMPT_CARD = "prompt_card",
25
+ WINDOW_API_CALL = "window_api_call",
26
+ }
27
+ //#endregion
1
28
  //#region src/types/external.d.ts
2
29
  declare enum ResponseCategory {
3
30
  Product = "product",
@@ -12,7 +39,7 @@ interface SearchResponseProduct {
12
39
  brand?: string;
13
40
  category?: string;
14
41
  availability?: string;
15
- url?: string;
42
+ url: string;
16
43
  responseId?: string;
17
44
  originalPrice?: number;
18
45
  salePrice?: number;
@@ -254,7 +281,7 @@ interface SearchResponseProductAttributes {
254
281
  category: ResponseCategory.Product;
255
282
  attributes: CamelCasedPropertiesDeep<SearchResponseProduct>;
256
283
  }
257
- interface ProductCardSkeletonProps {
284
+ interface ProductCardSkeletonProps$1 {
258
285
  layoutVariant: ProductCardLayoutVariant;
259
286
  aspectRatio: ProductCardImageAspectRatio;
260
287
  growWithContainer?: boolean;
@@ -269,4 +296,84 @@ interface ProductGridProps {
269
296
  cardsGrowWithContainer?: boolean;
270
297
  }
271
298
  //#endregion
272
- export { AnimatedProductCardOverrides, ProductCardConfig, ProductCardHoverVariant, ProductCardImageAspectRatio, ProductCardLayoutVariant, ProductCardSkeletonOverrides, ProductCardSkeletonProps, ProductCardVariant, ProductGridProps, ProductGridVariant, SearchResponseProduct, SearchResponseProductAttributes };
299
+ //#region src/components/ProductCard/ProductCard.d.ts
300
+ interface RatingSummaryProps {
301
+ stars: number;
302
+ reviewCount: number;
303
+ className?: string;
304
+ }
305
+ declare const RatingSummary: ({
306
+ stars,
307
+ reviewCount,
308
+ className
309
+ }: RatingSummaryProps) => react_jsx_runtime17.JSX.Element;
310
+ interface PriceSectionProps {
311
+ originalPrice?: string;
312
+ salePrice?: string;
313
+ pricePrefix?: string;
314
+ }
315
+ declare const PriceSection: ({
316
+ originalPrice,
317
+ salePrice,
318
+ pricePrefix
319
+ }: PriceSectionProps) => react_jsx_runtime17.JSX.Element;
320
+ interface ProductCardProps extends TestProps {
321
+ productCardConfig?: ProductCardConfig;
322
+ merchantShortName: string;
323
+ title: string;
324
+ url: string;
325
+ searchResponseId?: string;
326
+ productResponseId?: string;
327
+ cardDisplayLocation: ChatElementDisplayLocation.IN_CHAT | ChatElementDisplayLocation.PRODUCT_GRID;
328
+ imageUrl?: string;
329
+ originalPrice?: number;
330
+ averageRating?: number;
331
+ numberReviews?: number;
332
+ salePrice?: number;
333
+ variant?: ProductCardVariant;
334
+ hoverVariant?: ProductCardHoverVariant;
335
+ layoutVariant?: ProductCardLayoutVariant;
336
+ zoomOnHover?: boolean;
337
+ aspectRatio?: '3:4' | 'square' | 'none';
338
+ clickPosition?: number | null;
339
+ growWithContainer?: boolean;
340
+ handleClick?: (clickedUrl: string) => void;
341
+ }
342
+ declare const ProductCard: ({
343
+ productCardConfig,
344
+ merchantShortName,
345
+ imageUrl,
346
+ title,
347
+ url,
348
+ originalPrice,
349
+ averageRating,
350
+ numberReviews,
351
+ salePrice,
352
+ variant,
353
+ hoverVariant,
354
+ dataTestId,
355
+ layoutVariant,
356
+ zoomOnHover,
357
+ aspectRatio,
358
+ growWithContainer,
359
+ handleClick
360
+ }: ProductCardProps) => react_jsx_runtime17.JSX.Element;
361
+ //#endregion
362
+ //#region src/components/ProductCard/ProductCardSkeleton.d.ts
363
+ interface ProductCardSkeletonProps {
364
+ layoutVariant: ProductCardLayoutVariant;
365
+ aspectRatio?: '3:4' | 'square' | 'none';
366
+ growWithContainer?: boolean;
367
+ }
368
+ declare const ProductCardSkeleton: FC<ProductCardSkeletonProps>;
369
+ //#endregion
370
+ //#region src/components/ProductCard/productCardVariants.d.ts
371
+ /**
372
+ * Shared variant mapping configurations for ProductCard components
373
+ */
374
+ declare const variantClassMap: Map<ProductCardVariant, string[]>;
375
+ declare const variantHoverClassMap: Map<ProductCardHoverVariant, string[]>;
376
+ declare const variantTitleColorMap: Map<ProductCardVariant, string>;
377
+ declare const productCardLayoutVariantClasses: Record<ProductCardLayoutVariant, Record<string, string[]>>;
378
+ //#endregion
379
+ export { AnimatedProductCardOverrides, PriceSection, ProductCard, ProductCardConfig, ProductCardHoverVariant, ProductCardImageAspectRatio, ProductCardLayoutVariant, ProductCardSkeleton, ProductCardSkeletonOverrides, ProductCardSkeletonProps$1 as ProductCardSkeletonProps, ProductCardVariant, ProductGridProps, ProductGridVariant, RatingSummary, SearchResponseProductAttributes, productCardLayoutVariantClasses, variantClassMap, variantHoverClassMap, variantTitleColorMap };
@@ -1,4 +1,4 @@
1
- import { ColorNames, colorVar } from "./colorsConfig-CKiMYHO_.js";
1
+ import { ColorNames, colorVar } from "./colorsConfig-BQlaCfxi.js";
2
2
 
3
3
  //#region src/components/SearchResultsFilterSidebar/searchFilterSidebarVariants.ts
4
4
  const searchFilterSidebarVariantClasses = {
@@ -1,4 +1,4 @@
1
- const require_colorsConfig = require('./colorsConfig-DulwYRIk.cjs');
1
+ const require_colorsConfig = require('./colorsConfig-DCvy_dV4.cjs');
2
2
 
3
3
  //#region src/components/SearchResultsFilterSidebar/searchFilterSidebarVariants.ts
4
4
  const searchFilterSidebarVariantClasses = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@envive-ai/react-toolkit",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "React component library for Envive services.",
5
5
  "keywords": [
6
6
  "react",
@@ -24,6 +24,7 @@
24
24
  "prepublish": "npm run build"
25
25
  },
26
26
  "dependencies": {
27
+ "@envive-ai/react-hooks": "^0.1.1",
27
28
  "@envive-ai/react-icons": "0.1.1",
28
29
  "classnames": "^2.5.1",
29
30
  "framer-motion": "^12.23.12",
@@ -39,6 +40,10 @@
39
40
  "typescript": "~5.8.3"
40
41
  },
41
42
  "exports": {
43
+ "./Accordion": {
44
+ "import": "./dist/Accordion/index.js",
45
+ "require": "./dist/Accordion/index.cjs"
46
+ },
42
47
  "./ButtonBase": {
43
48
  "import": "./dist/ButtonBase/index.js",
44
49
  "require": "./dist/ButtonBase/index.cjs"
@@ -63,6 +68,10 @@
63
68
  "import": "./dist/ProductGrid/index.js",
64
69
  "require": "./dist/ProductGrid/index.cjs"
65
70
  },
71
+ "./SearchAutocomplete": {
72
+ "import": "./dist/SearchAutocomplete/index.js",
73
+ "require": "./dist/SearchAutocomplete/index.cjs"
74
+ },
66
75
  "./SearchFilter": {
67
76
  "import": "./dist/SearchFilter/index.js",
68
77
  "require": "./dist/SearchFilter/index.cjs"
@@ -71,10 +80,6 @@
71
80
  "import": "./dist/SearchInput/index.js",
72
81
  "require": "./dist/SearchInput/index.cjs"
73
82
  },
74
- "./SearchInputAutocomplete": {
75
- "import": "./dist/SearchInputAutocomplete/index.js",
76
- "require": "./dist/SearchInputAutocomplete/index.cjs"
77
- },
78
83
  "./SearchInputForm": {
79
84
  "import": "./dist/SearchInputForm/index.js",
80
85
  "require": "./dist/SearchInputForm/index.cjs"
@@ -0,0 +1,90 @@
1
+ import { motion } from 'framer-motion';
2
+ import { useRef, useState } from 'react';
3
+ import classNames from 'classnames';
4
+ import { Text } from '@envive-ai/react-toolkit/Text';
5
+ import ChevronDown from '@envive-ai/react-icons/ChevronDown';
6
+
7
+ interface AccordionProps {
8
+ title: string;
9
+ content: React.ReactNode;
10
+ }
11
+
12
+ const ANIMATION_DURATION = 0.3;
13
+
14
+ export const Accordion = ({ title, content }: AccordionProps) => {
15
+ const [isOpen, setIsOpen] = useState(false);
16
+
17
+ const contentRef = useRef<HTMLDivElement>(null);
18
+
19
+ const titleWrapperClasses = classNames({
20
+ 'spiffy-tw-border-b': true,
21
+ 'spiffy-tw-border-[--spiffy-colors-border-light]': true,
22
+ 'spiffy-tw-pb-2': true,
23
+ 'spiffy-tw-flex': true,
24
+ 'spiffy-tw-justify-between': true,
25
+ 'spiffy-tw-items-center': true,
26
+ 'spiffy-tw-w-full': true,
27
+ 'spiffy-tw-group': true,
28
+ });
29
+
30
+ const titleClasses = classNames({
31
+ 'spiffy-tw-uppercase': true,
32
+ 'spiffy-tw-text-[--spiffy-colors-text-primary]': true,
33
+ '!spiffy-tw-font-[400]': true,
34
+ 'group-aria-expanded:!spiffy-tw-font-medium': true,
35
+ });
36
+
37
+ const contentClasses = classNames({
38
+ 'spiffy-tw-overflow-hidden': true,
39
+ });
40
+
41
+ return (
42
+ <div>
43
+ <button
44
+ aria-expanded={isOpen}
45
+ type="button"
46
+ className={titleWrapperClasses}
47
+ onClick={() => setIsOpen(!isOpen)}
48
+ >
49
+ <Text variant="body4" className={titleClasses}>
50
+ {title}
51
+ </Text>
52
+ <motion.div
53
+ variants={{
54
+ open: {
55
+ rotate: 180,
56
+ },
57
+ closed: {
58
+ rotate: 360,
59
+ },
60
+ }}
61
+ animate={isOpen ? 'open' : 'closed'}
62
+ transition={{ duration: ANIMATION_DURATION, ease: 'easeOut' }}
63
+ >
64
+ <ChevronDown />
65
+ </motion.div>
66
+ </button>
67
+ <motion.div
68
+ variants={{
69
+ open: {
70
+ height: 'auto',
71
+ marginTop: '24px',
72
+ marginBottom: '24px',
73
+ },
74
+ closed: {
75
+ height: '0px',
76
+ marginTop: '0px',
77
+ marginBottom: '0px',
78
+ },
79
+ }}
80
+ className={contentClasses}
81
+ initial={{ height: 0 }}
82
+ animate={isOpen ? 'open' : 'closed'}
83
+ transition={{ duration: ANIMATION_DURATION, ease: 'easeOut' }}
84
+ ref={contentRef}
85
+ >
86
+ {content}
87
+ </motion.div>
88
+ </div>
89
+ );
90
+ };
@@ -0,0 +1 @@
1
+ export * from './Accordion';
@@ -0,0 +1,70 @@
1
+ import classNames from 'classnames';
2
+ import ScrollContainer from 'react-indiana-drag-scroll';
3
+ import { SelectedFilterOption } from 'src/atoms/search/types';
4
+ import { Text } from '@envive-ai/react-toolkit/Text';
5
+
6
+ interface AppliedFiltersScrollbarProps {
7
+ selectedFilterOptions: SelectedFilterOption[];
8
+ filterBarClassNames: string;
9
+ filterDefaultClasses: string;
10
+ filterHoverClasses: string;
11
+ appliedFilterBackgroundClasses: string;
12
+ onRemoveFilter: (filter: SelectedFilterOption) => void;
13
+ }
14
+
15
+ export const AppliedFiltersScrollbar = ({
16
+ selectedFilterOptions,
17
+ filterBarClassNames,
18
+ filterDefaultClasses,
19
+ filterHoverClasses,
20
+ appliedFilterBackgroundClasses,
21
+ onRemoveFilter,
22
+ }: AppliedFiltersScrollbarProps) => {
23
+ if (selectedFilterOptions.length === 0) {
24
+ return null;
25
+ }
26
+
27
+ // Extract border and text classes from filterDefaultClasses, excluding background because everything is shared between filters except for the applied filters background
28
+ const filterDefaultWithoutBg = filterDefaultClasses
29
+ .replace(/spiffy-tw-bg-\[--spiffy-colors-[^\]]+\]/g, '')
30
+ .trim();
31
+ const buttonClasses = classNames(
32
+ ' spiffy-tw-flex spiffy-tw-items-center spiffy-tw-rounded-full spiffy-tw-px-[8px] spiffy-tw-py-[4px] spiffy-tw-whitespace-nowrap',
33
+ filterHoverClasses,
34
+ filterDefaultWithoutBg,
35
+ appliedFilterBackgroundClasses,
36
+ );
37
+ const iconColor = 'currentColor'; // match with text color
38
+
39
+ return (
40
+ <ScrollContainer className={filterBarClassNames} hideScrollbars>
41
+ {selectedFilterOptions.map((filter) => {
42
+ return (
43
+ <button
44
+ key={filter.id}
45
+ className={buttonClasses}
46
+ type="button"
47
+ onClick={() => onRemoveFilter(filter)}
48
+ aria-label={`Remove filter: ${filter.displayName}`}
49
+ >
50
+ <div className="spiffy-tw-flex spiffy-tw-items-center spiffy-tw-gap-[8px]">
51
+ <Text variant="body3">{filter.displayName}</Text>
52
+ <svg
53
+ xmlns="http://www.w3.org/2000/svg"
54
+ width="10"
55
+ height="10"
56
+ viewBox="0 0 10 10"
57
+ fill="none"
58
+ >
59
+ <path
60
+ d="M4.59766 4.29297L8.48535 0.405273L9.19238 1.1123L5.30469 5L9.19238 8.8877L8.48535 9.59473L4.59766 5.70703L0.707031 9.59766L0 8.89062L3.89062 5L0 1.10938L0.707031 0.402344L4.59766 4.29297Z"
61
+ fill={iconColor}
62
+ />
63
+ </svg>
64
+ </div>
65
+ </button>
66
+ );
67
+ })}
68
+ </ScrollContainer>
69
+ );
70
+ };
@@ -0,0 +1,52 @@
1
+ import classNames from 'classnames';
2
+ import ScrollContainer from 'react-indiana-drag-scroll';
3
+ import { Text } from '@envive-ai/react-toolkit/Text';
4
+
5
+ interface DynamicFiltersScrollbarProps {
6
+ availableDynamicFilters: { name: string; displayName: string }[];
7
+ filterBarClassNames: string;
8
+ filterDefaultClasses: string;
9
+ filterHoverClasses: string;
10
+ onToggleDynamicFilter: ({
11
+ filter,
12
+ dynamicFilterDisplayName,
13
+ }: {
14
+ filter: string;
15
+ dynamicFilterDisplayName: string;
16
+ }) => void;
17
+ }
18
+
19
+ export const DynamicFiltersScrollbar = ({
20
+ availableDynamicFilters,
21
+ filterBarClassNames,
22
+ filterDefaultClasses,
23
+ filterHoverClasses,
24
+ onToggleDynamicFilter,
25
+ }: DynamicFiltersScrollbarProps) => {
26
+ return (
27
+ <ScrollContainer className={filterBarClassNames} hideScrollbars>
28
+ {availableDynamicFilters.map(({ name, displayName }) => {
29
+ const buttonClasses = classNames(
30
+ 'spiffy-tw-px-[12px] spiffy-tw-py-2 spiffy-tw-rounded-full spiffy-tw-border spiffy-tw-whitespace-nowrap ',
31
+ filterHoverClasses,
32
+ filterDefaultClasses,
33
+ );
34
+ return (
35
+ <button
36
+ key={name}
37
+ type="button"
38
+ className={buttonClasses}
39
+ onClick={() => {
40
+ onToggleDynamicFilter({
41
+ filter: name,
42
+ dynamicFilterDisplayName: displayName,
43
+ });
44
+ }}
45
+ >
46
+ <Text variant="body3">{displayName}</Text>
47
+ </button>
48
+ );
49
+ })}
50
+ </ScrollContainer>
51
+ );
52
+ };
@@ -1,25 +1,26 @@
1
1
  import classNames from 'classnames';
2
2
  import { MdStar } from 'react-icons/md';
3
- import { Text } from 'src/components/Text/Text';
4
3
  import {
5
4
  variantClassMap,
6
5
  variantHoverClassMap,
7
6
  productCardLayoutVariantClasses,
8
7
  variantTitleColorMap,
9
8
  } from './productCardVariants';
10
- import { Headline } from '../Headline/Headline';
11
- import { ImageWithFallback } from 'src/components/ImageWithFallback/ImageWithFallback';
12
- import type {
9
+ import { ChatElementDisplayLocation } from 'src/config/chatElementDisplayLocation';
10
+ import Logger from 'src/logging/logger';
11
+ import { TestProps } from 'src/test/types';
12
+ import { Headline } from '../Headline';
13
+ import { ImageWithFallback } from '../ImageWithFallback';
14
+ import { Spinner } from '../Spinner';
15
+ import {
13
16
  ProductCardConfig,
17
+ ProductCardVariant,
14
18
  ProductCardHoverVariant,
15
19
  ProductCardLayoutVariant,
16
- ProductCardVariant,
17
20
  } from './types';
18
- import type { TestProps } from 'src/test/types';
19
- import type { ChatElementDisplayLocation } from 'src/config/chatElementDisplayLocation';
20
- import Logger from 'src/logging/logger';
21
- import { Spinner } from '../Spinner/Spinner';
21
+ import { Text } from 'src/components/Text/Text';
22
22
  import { formatPrice } from 'src/util/formatPrice';
23
+ import { useImageResolver } from '@envive-ai/react-hooks/hooks';
23
24
 
24
25
  const formatReviews = (stars: number) =>
25
26
  String(
@@ -95,11 +96,26 @@ export const PriceSection = ({ originalPrice, salePrice, pricePrefix }: PriceSec
95
96
  );
96
97
  };
97
98
 
99
+ // export const formatPrice = (price?: number, currency: string = '$'): string => {
100
+ // if (price == null) {
101
+ // return '';
102
+ // }
103
+
104
+ // const options: Intl.NumberFormatOptions = {};
105
+
106
+ // if (!Number.isInteger(price)) {
107
+ // options.minimumFractionDigits = 2;
108
+ // options.maximumFractionDigits = 2;
109
+ // }
110
+
111
+ // return `${currency}${price.toLocaleString('en-US', options)}`;
112
+ // };
113
+
98
114
  interface ProductCardProps extends TestProps {
99
115
  productCardConfig?: ProductCardConfig;
100
116
  merchantShortName: string;
101
117
  title: string;
102
- url?: string;
118
+ url: string;
103
119
  searchResponseId?: string;
104
120
  productResponseId?: string;
105
121
  cardDisplayLocation: ChatElementDisplayLocation.IN_CHAT | ChatElementDisplayLocation.PRODUCT_GRID;
@@ -115,7 +131,7 @@ interface ProductCardProps extends TestProps {
115
131
  aspectRatio?: '3:4' | 'square' | 'none';
116
132
  clickPosition?: number | null;
117
133
  growWithContainer?: boolean;
118
- handleClick: (clickedUrl: string) => void;
134
+ handleClick?: (clickedUrl: string) => void;
119
135
  }
120
136
 
121
137
  export const ProductCard = ({
@@ -124,6 +140,8 @@ export const ProductCard = ({
124
140
  imageUrl,
125
141
  title,
126
142
  url,
143
+ // searchResponseId,
144
+ // productResponseId,
127
145
  originalPrice,
128
146
  averageRating,
129
147
  numberReviews,
@@ -132,13 +150,14 @@ export const ProductCard = ({
132
150
  hoverVariant,
133
151
  dataTestId,
134
152
  layoutVariant = 'normal',
153
+ // cardDisplayLocation,
135
154
  zoomOnHover = false,
136
155
  aspectRatio = 'none',
156
+ // clickPosition = null,
137
157
  growWithContainer = false,
138
158
  handleClick,
139
159
  }: ProductCardProps) => {
140
- // const orgUIConfig = useAtomValue(orgUIConfigAtom);
141
- // const { productCardConfig } = orgUIConfig;
160
+ const { resolve } = useImageResolver();
142
161
 
143
162
  const finalVariant = variant ?? productCardConfig?.variant ?? 'filled';
144
163
  const finalHoverVariant = hoverVariant ?? productCardConfig?.hoverVariant ?? 'backgroundDark';
@@ -265,15 +284,13 @@ export const ProductCard = ({
265
284
 
266
285
  return (
267
286
  <div className={containerClassnames} data-testid={dataTestId}>
268
- <a href={url} onClick={() => handleClick(url || '')} target="_self" draggable={false}>
287
+ <a href={url} onClick={() => handleClick(url)} target="_self" draggable={false}>
269
288
  <div className={verticalContainerClassnames}>
270
289
  <div className={imageClipContainerClassnames}>
271
290
  <div className={imageContainerClassnames}>
272
291
  {imageUrl && (
273
292
  <ImageWithFallback
274
- // TODO: Fix once
275
- // src={resolve(imageUrl, layoutVariant === 'tall' ? 300 : 178)}
276
- src={imageUrl}
293
+ src={resolve(imageUrl, layoutVariant === 'tall' ? 300 : 178)}
277
294
  alt={title}
278
295
  fallback={<Spinner className="spiffy-tw-w-6 spiffy-tw-h-6" />}
279
296
  imageClassnames={imageClassnames}
@@ -1,4 +1,4 @@
1
- import type { ResponseCategory, SearchResponseProduct } from 'src/types/external';
1
+ import { ResponseCategory, SearchResponseProduct } from '@spiffy-ai/commerce-api-client';
2
2
  import type { CamelCasedPropertiesDeep } from 'src/util/camelCasedPropertiesDeep';
3
3
 
4
4
  export enum ProductCardSkeletonOverrides {
@@ -1,9 +1,9 @@
1
- import type { ProductCardConfig, ProductGridVariant } from '../ProductCard/types';
2
- import { ProductCard } from '../ProductCard/ProductCard';
1
+ import { ChatElementDisplayLocation } from 'src/config/chatElementDisplayLocation';
2
+ import { ProductGridVariant, ProductCardConfig, ProductCard } from '../ProductCard';
3
3
  import { productGridVariantClasses } from './productGridVariants';
4
4
  import classNames from 'classnames';
5
- import { ChatElementDisplayLocation } from 'src/config/chatElementDisplayLocation';
6
- import { SearchResponseProduct } from 'src/types/external';
5
+ import { SearchResponseProduct } from '@spiffy-ai/commerce-api-client';
6
+ import { CamelCasedPropertiesDeep } from 'src/util/camelCasedPropertiesDeep';
7
7
 
8
8
  interface ProductGridProps {
9
9
  productList: SearchResponseProduct[];
@@ -13,7 +13,6 @@ interface ProductGridProps {
13
13
  merchantShortName: string;
14
14
  searchResponseId: string;
15
15
  cardsGrowWithContainer?: boolean;
16
- handleClick: (clickedUrl: string) => void;
17
16
  }
18
17
 
19
18
  export const ProductGrid = ({
@@ -24,7 +23,6 @@ export const ProductGrid = ({
24
23
  merchantShortName,
25
24
  searchResponseId,
26
25
  cardsGrowWithContainer = true,
27
- handleClick,
28
26
  }: ProductGridProps) => {
29
27
  const {
30
28
  productCardVariant,
@@ -41,33 +39,35 @@ export const ProductGrid = ({
41
39
 
42
40
  return (
43
41
  <div className={productGridClasses}>
44
- {productList.map((product: (typeof productList)[0], index: number) => (
45
- <div key={product.id} className={cardContainerClasses}>
46
- <ProductCard
47
- productCardConfig={productCardConfig}
48
- merchantShortName={merchantShortName}
49
- key={product.id}
50
- imageUrl={product.imageUrl}
51
- searchResponseId={searchResponseId}
52
- productResponseId={product.responseId}
53
- title={product.title}
54
- url={product.url}
55
- originalPrice={product.originalPrice}
56
- salePrice={product.salePrice}
57
- averageRating={product.averageRating}
58
- numberReviews={product.numberReviews}
59
- cardDisplayLocation={ChatElementDisplayLocation.PRODUCT_GRID}
60
- layoutVariant={productCardLayoutVariant}
61
- variant={productCardVariant}
62
- hoverVariant={productCardHoverVariant}
63
- zoomOnHover={zoomOnHover}
64
- aspectRatio={productCardImageAspectRatio}
65
- clickPosition={index}
66
- growWithContainer={cardsGrowWithContainer}
67
- handleClick={handleClick}
68
- />
69
- </div>
70
- ))}
42
+ {productList.map((product: SearchResponseProduct, index: number) => {
43
+ const camelCasedProduct: CamelCasedPropertiesDeep<SearchResponseProduct> = product;
44
+ return (
45
+ <div key={camelCasedProduct.id} className={cardContainerClasses}>
46
+ <ProductCard
47
+ productCardConfig={productCardConfig}
48
+ merchantShortName={merchantShortName}
49
+ key={camelCasedProduct.id}
50
+ imageUrl={camelCasedProduct.imageUrl}
51
+ searchResponseId={searchResponseId}
52
+ productResponseId={camelCasedProduct.responseId}
53
+ title={camelCasedProduct.title}
54
+ url={camelCasedProduct.url}
55
+ originalPrice={camelCasedProduct.originalPrice}
56
+ salePrice={camelCasedProduct.salePrice}
57
+ averageRating={camelCasedProduct.averageRating}
58
+ numberReviews={camelCasedProduct.numberReviews}
59
+ cardDisplayLocation={ChatElementDisplayLocation.PRODUCT_GRID}
60
+ layoutVariant={productCardLayoutVariant}
61
+ variant={productCardVariant}
62
+ hoverVariant={productCardHoverVariant}
63
+ zoomOnHover={zoomOnHover}
64
+ aspectRatio={productCardImageAspectRatio}
65
+ clickPosition={index}
66
+ growWithContainer={cardsGrowWithContainer}
67
+ />
68
+ </div>
69
+ );
70
+ })}
71
71
  </div>
72
72
  );
73
73
  };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { motion } from 'framer-motion';
3
3
  import classNames from 'classnames';
4
- import OutlinedStar from '@envive-ai/react-icons/src/OutlinedStar';
4
+ import OutlinedStar from '@envive-ai/react-icons/OutlinedStar';
5
5
 
6
6
  interface GlobalSearchAutocompleteProps {
7
7
  id: string;
@@ -1,12 +1,12 @@
1
1
  import React, { useRef, useImperativeHandle } from 'react';
2
2
  import classNames from 'classnames';
3
- import MagnifyingGlassStarVariant from '@envive-ai/react-icons/src/MagnifyingGlassStarVariant';
4
- import CloseIcon from '@envive-ai/react-icons/src/IconClose';
5
- import { TextInput } from 'src/components/TextInput/TextInput';
3
+ import MagnifyingGlassStarVariant from '@envive-ai/react-icons/MagnifyingGlassStarVariant';
4
+ import { SearchInputVariant } from '../SearchInputForm';
5
+ import { TextInput } from '../TextInput';
6
6
  import { searchInputVariantClasses } from './searchInputVariants';
7
- import type { SearchInputVariant } from '../SearchInputForm/types';
7
+ import { IconClose } from '@envive-ai/react-icons/src/index.js';
8
8
 
9
- export interface SearchInputProps {
9
+ interface SearchInputProps {
10
10
  searchInputVariant?: SearchInputVariant;
11
11
  value: string;
12
12
  placeholder?: string;
@@ -126,7 +126,7 @@ export const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(
126
126
  aria-label="Clear search input"
127
127
  type="button"
128
128
  >
129
- <CloseIcon className={closeButtonIconClassName} />
129
+ <IconClose className={closeButtonIconClassName} />
130
130
  </button>
131
131
  )}
132
132
  </div>