@akinon/pz-similar-products 1.92.0-snapshot-ZERO-3457-20250627111231 → 1.93.0-rc.46

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/CHANGELOG.md CHANGED
@@ -1,7 +1,117 @@
1
1
  # @akinon/pz-similar-products
2
2
 
3
- ## 1.92.0-snapshot-ZERO-3457-20250627111231
3
+ ## 1.93.0-rc.46
4
4
 
5
5
  ### Minor Changes
6
6
 
7
- - d99a6a7: ZERO-3457_1: Fixed the settings prop and made sure everything is customizable.
7
+ - 54e31792: ZERO-3532: Added customize options to icons
8
+ - 174bf3a5: ZERO-3533: Refactor similar products API endpoints to support array search parameters and improve query handling
9
+ - d8be48fb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
10
+ - 143be2b9: ZERO-3457: Crop styles are customizable and logic improved for rendering similar products modal
11
+ - 8b1d24eb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
12
+ - d99a6a7d: ZERO-3457: Fixed the settings prop and made sure everything is customizable.
13
+ - 59b275ca: ZERO-3532: Pass settings prop to SimilarProductsButton for enhanced functionality
14
+ - d606f4ac: ZERO-3481: Add locale and currency to list endpoint
15
+
16
+ ## 1.92.0-rc.45
17
+
18
+ ## 1.92.0-rc.44
19
+
20
+ ## 1.92.0-rc.43
21
+
22
+ ## 1.92.0-rc.42
23
+
24
+ ### Minor Changes
25
+
26
+ - 54e31792: ZERO-3532: Added customize options to icons
27
+ - 174bf3a5: ZERO-3533: Refactor similar products API endpoints to support array search parameters and improve query handling
28
+ - d8be48fb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
29
+ - 143be2b9: ZERO-3457: Crop styles are customizable and logic improved for rendering similar products modal
30
+ - 8b1d24eb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
31
+ - d99a6a7d: ZERO-3457: Fixed the settings prop and made sure everything is customizable.
32
+ - 59b275ca: ZERO-3532: Pass settings prop to SimilarProductsButton for enhanced functionality
33
+ - d606f4ac: ZERO-3481: Add locale and currency to list endpoint
34
+
35
+ ## 1.92.0-rc.41
36
+
37
+ ## 1.92.0-rc.40
38
+
39
+ ## 1.92.0-rc.39
40
+
41
+ ### Minor Changes
42
+
43
+ - 174bf3a: ZERO-3533: Refactor similar products API endpoints to support array search parameters and improve query handling
44
+
45
+ ## 1.92.0-rc.38
46
+
47
+ ## 1.92.0-rc.37
48
+
49
+ ## 1.92.0-rc.36
50
+
51
+ ## 1.92.0-rc.35
52
+
53
+ ## 1.92.0-rc.34
54
+
55
+ ## 1.92.0-rc.33
56
+
57
+ ### Minor Changes
58
+
59
+ - 59b275c: ZERO-3532: Pass settings prop to SimilarProductsButton for enhanced functionality
60
+
61
+ ## 1.92.0-rc.32
62
+
63
+ ### Minor Changes
64
+
65
+ - 54e3179: ZERO-3532: Added customize options to icons
66
+
67
+ ## 1.92.0-rc.31
68
+
69
+ ## 1.92.0-rc.30
70
+
71
+ ## 1.92.0-rc.29
72
+
73
+ ## 1.92.0-rc.28
74
+
75
+ ## 1.92.0-rc.27
76
+
77
+ ### Minor Changes
78
+
79
+ - d606f4a: ZERO-3481: Add locale and currency to list endpoint
80
+
81
+ ## 1.92.0-rc.26
82
+
83
+ ## 1.92.0-rc.25
84
+
85
+ ## 1.92.0-rc.24
86
+
87
+ ## 1.92.0-rc.23
88
+
89
+ ## 1.92.0-rc.22
90
+
91
+ ### Minor Changes
92
+
93
+ - 143be2b: ZERO-3457: Crop styles are customizable and logic improved for rendering similar products modal
94
+
95
+ ## 1.92.0-rc.21
96
+
97
+ ### Minor Changes
98
+
99
+ - d99a6a7: ZERO-3457: Fixed the settings prop and made sure everything is customizable.
100
+
101
+ ## 1.92.0-rc.20
102
+
103
+ ### Minor Changes
104
+
105
+ - 8b1d24e: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
106
+
107
+ ## 1.92.0-rc.19
108
+
109
+ ### Minor Changes
110
+
111
+ - d8be48f: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
112
+
113
+ ## 1.92.0-rc.18
114
+
115
+ ## 1.92.0-rc.17
116
+
117
+ ## 1.92.0-rc.16
package/README.md CHANGED
@@ -10,6 +10,7 @@
10
10
 
11
11
  - [Features](#markdown-header-features)
12
12
  - [Installation](#markdown-header-installation)
13
+ - [Icon Customization](#markdown-header-icon-customization)
13
14
  - [Quick Start](#markdown-header-quick-start)
14
15
  - [Available Components](#markdown-header-available-components)
15
16
  - [Configuration](#markdown-header-configuration)
@@ -64,6 +65,7 @@
64
65
 
65
66
  - **🖼️ Visual Search**: AI-powered image-based product discovery
66
67
  - **✂️ Image Cropping**: Built-in cropping functionality with manual confirmation for precise searches
68
+ - **🔤 Text Search**: Search similar products by text description with customizable input
67
69
  - **🎛️ Advanced Filtering**: Dynamic facet-based filtering system
68
70
  - **📄 Multiple Pagination Modes**: Traditional pagination, load more button, and infinite scroll
69
71
  - **🎨 Granular Customization**: 50+ style targets and 30+ render points
@@ -79,6 +81,94 @@ npx @akinon/projectzero@latest --plugins
79
81
 
80
82
  Select `pz-similar-products` from the plugin list during installation.
81
83
 
84
+ ## Icon Customization
85
+
86
+ The plugin provides complete control over icon appearance and behavior through two complementary approaches:
87
+
88
+ ### Icon Names (`iconNames`)
89
+
90
+ Change which icons are displayed by specifying different icon names:
91
+
92
+ ```tsx
93
+ const iconCustomization = {
94
+ iconNames: {
95
+ searchButton: 'magnifier', // Search button (default: 'search')
96
+ modalClose: 'x', // Modal close buttons (default: 'close')
97
+ filter: 'funnel', // Filter button (default: 'filter')
98
+ filterRemove: 'trash', // Filter tag remove buttons (default: 'close')
99
+ modalSearch: 'search-outline', // Modal search button (default: 'search')
100
+ modalSearchClear: 'clear', // Search input clear button (default: 'close')
101
+ imageSearchButton: 'upload' // Image search button (default: 'search')
102
+ }
103
+ };
104
+ ```
105
+
106
+ ### Icon Styles (`customStyles`)
107
+
108
+ Customize the visual appearance of icons with CSS classes:
109
+
110
+ ```tsx
111
+ const iconStyling = {
112
+ customStyles: {
113
+ searchButtonIcon: 'fill-blue-500 hover:fill-blue-600 transition-colors',
114
+ modalCloseIcon: 'text-red-500 hover:text-red-700 w-4 h-4',
115
+ filterIcon: 'text-purple-500 w-5 h-5',
116
+ filterRemoveIcon: 'text-orange-500 hover:text-orange-700 w-3 h-3',
117
+ imageSearchButtonIcon: 'text-blue-500 hover:text-blue-600 w-5 h-5'
118
+ }
119
+ };
120
+ ```
121
+
122
+ ### Complete Icon Customization Example
123
+
124
+ ```tsx
125
+ const completeIconSettings = {
126
+ // Change icon names
127
+ iconNames: {
128
+ searchButton: 'search-alt',
129
+ modalClose: 'times',
130
+ filter: 'filter-alt',
131
+ filterRemove: 'remove',
132
+ modalSearch: 'magnifying-glass',
133
+ modalSearchClear: 'clear-alt',
134
+ imageSearchButton: 'upload-cloud'
135
+ },
136
+
137
+ // Style the icons
138
+ customStyles: {
139
+ searchButtonIcon:
140
+ 'fill-indigo-500 hover:fill-indigo-600 transition-all duration-200',
141
+ modalCloseIcon: 'text-gray-500 hover:text-gray-700 w-5 h-5',
142
+ filterIcon: 'text-blue-500 hover:text-blue-600 w-4 h-4',
143
+ filterRemoveIcon:
144
+ 'text-red-400 hover:text-red-600 w-3 h-3 transition-colors',
145
+ modalSearchIcon: 'text-green-500 hover:text-green-600',
146
+ modalSearchClearIcon: 'text-gray-400 hover:text-gray-600',
147
+ imageSearchButtonIcon: 'text-indigo-500 hover:text-indigo-600 w-5 h-5'
148
+ }
149
+ };
150
+
151
+ // Usage
152
+ <PluginModule
153
+ component={Component.ProductImageSearchFeature}
154
+ props={{
155
+ product,
156
+ activeIndex,
157
+ settings: completeIconSettings
158
+ }}
159
+ />;
160
+ ```
161
+
162
+ ### Available Icon Customization Points
163
+
164
+ - **Search Button** (`searchButton`): Main search button icon in product images
165
+ - **Modal Close** (`modalClose`): Close buttons in modals and filter tags
166
+ - **Filter** (`filter`): Filter toggle button icon
167
+ - **Filter Remove** (`filterRemove`): Remove icons in active filter tags
168
+ - **Modal Search** (`modalSearch`): Search button icon in text search input
169
+ - **Modal Search Clear** (`modalSearchClear`): Clear button icon in text search input
170
+ - **Image Search Button** (`imageSearchButton`): Camera/upload icon in header search feature
171
+
82
172
  ## Quick Start
83
173
 
84
174
  ### Plugin Module Integration
@@ -167,6 +257,7 @@ interface SimilarProductsSettings {
167
257
  resultsPerPage?: number; // Products per page (default: 20)
168
258
  enableCropping?: boolean; // Enable image cropping (default: true)
169
259
  enableFileUpload?: boolean; // Enable file upload (default: true)
260
+ enableTextSearch?: boolean; // Enable text search input (default: false)
170
261
 
171
262
  // Pagination settings
172
263
  paginationType?: 'pagination' | 'load-more' | 'infinite-scroll'; // Pagination mode (default: 'pagination')
@@ -200,6 +291,21 @@ interface SimilarProductsSettings {
200
291
  sortDropdown?: string;
201
292
  filterToggleButton?: string;
202
293
 
294
+ // Text search input
295
+ modalSearchInput?: string;
296
+ modalSearchContainer?: string;
297
+ modalSearchButton?: string;
298
+ modalSearchIcon?: string;
299
+ modalSearchClearButton?: string;
300
+ modalSearchClearIcon?: string;
301
+
302
+ // Icon customization
303
+ searchButtonIcon?: string; // Search button icon styling
304
+ modalCloseIcon?: string; // Modal close button icons styling
305
+ filterIcon?: string; // Filter button icon styling
306
+ filterRemoveIcon?: string; // Filter tag remove icons styling
307
+ imageSearchButtonIcon?: string; // Image search button icon styling
308
+
203
309
  // Filter sidebar mobile
204
310
  filterSidebarMobileHeader?: string;
205
311
  filterSidebarMobileTitle?: string; // NEW: Mobile title
@@ -266,11 +372,35 @@ interface SimilarProductsSettings {
266
372
  imageSearchTipsTitle?: string; // NEW: Tips title
267
373
  imageSearchTipsList?: string; // NEW: Tips list
268
374
  imageSearchTipsItem?: string; // NEW: Individual tip
375
+ imageSearchModalOverlay?: string; // NEW: Image search modal overlay
269
376
 
270
377
  // Mobile active filters
271
378
  mobileActiveFilters?: string;
272
379
  mobileActiveFilterTag?: string;
273
380
  mobileClearAllButton?: string;
381
+
382
+ // New crop-related custom styles
383
+ cropComponent?: string;
384
+ cropImage?: string;
385
+ cropImageActive?: string;
386
+ cropImageNonCropping?: string;
387
+ cropImageContainer?: string;
388
+ cropOverlay?: string;
389
+ cropSelection?: string;
390
+ cropSelectionBorder?: string;
391
+ cropOverlayBackground?: string;
392
+ cropSelectionHighlight?: string;
393
+ };
394
+
395
+ // Icon name customization
396
+ iconNames?: {
397
+ searchButton?: string; // Search button icon name (default: 'search')
398
+ modalClose?: string; // Modal close button icon name (default: 'close')
399
+ filter?: string; // Filter button icon name (default: 'filter')
400
+ filterRemove?: string; // Filter tag remove icon name (default: 'close')
401
+ modalSearch?: string; // Modal search button icon name (default: 'search')
402
+ modalSearchClear?: string; // Modal search clear button icon name (default: 'close')
403
+ imageSearchButton?: string; // Image search button icon name (default: 'search')
274
404
  };
275
405
 
276
406
  // 25+ render functions for granular control
@@ -291,6 +421,8 @@ interface SimilarProductsSettings {
291
421
  renderItemCount?: (props) => React.ReactNode;
292
422
  renderSortDropdown?: (props) => React.ReactNode;
293
423
  renderFilterToggleButton?: (props) => React.ReactNode;
424
+ renderModalSearchInput?: (props) => React.ReactNode;
425
+ renderSearchIcon?: (props) => React.ReactNode;
294
426
  // ... see examples for complete list
295
427
  };
296
428
  filterSidebar?: {
@@ -328,6 +460,105 @@ interface SimilarProductsSettings {
328
460
  }
329
461
  ```
330
462
 
463
+ ## Text Search Integration
464
+
465
+ The plugin features a built-in text search functionality that allows users to search for similar products using descriptive text.
466
+
467
+ ### Text Search Features
468
+
469
+ 1. **Search Input**: Appears only when API results are available
470
+ 2. **Enter Key Support**: Press Enter to trigger search
471
+ 3. **Search Icon**: Clickable icon for mobile users
472
+ 4. **Clear Button**: X button to clear text and trigger search without text
473
+ 5. **Custom Styling**: Fully customizable input, button, and icon
474
+ 6. **Custom Icon**: Replaceable search icon via render functions
475
+
476
+ ### Basic Text Search Configuration
477
+
478
+ ```tsx
479
+ const textSearchSettings = {
480
+ enableTextSearch: true, // Enable text search input
481
+
482
+ customStyles: {
483
+ modalSearchContainer: 'relative flex items-center',
484
+ modalSearchInput:
485
+ 'h-10 px-4 pr-20 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500',
486
+ modalSearchButton:
487
+ 'absolute right-2 top-1/2 -translate-y-1/2 p-2 hover:bg-gray-100 rounded-md',
488
+ modalSearchIcon: 'text-gray-500',
489
+ modalSearchClearButton:
490
+ 'absolute right-12 top-1/2 -translate-y-1/2 p-2 hover:bg-gray-100 rounded-md',
491
+ modalSearchClearIcon: 'text-gray-400 hover:text-gray-600'
492
+ }
493
+ };
494
+ ```
495
+
496
+ ### Custom Search Icon
497
+
498
+ ```tsx
499
+ const customIconSettings = {
500
+ enableTextSearch: true,
501
+
502
+ customRenderers: {
503
+ render: {
504
+ modal: {
505
+ renderSearchIcon: ({ disabled, onClick }) => (
506
+ <svg
507
+ className="w-5 h-5 text-blue-500 cursor-pointer hover:text-blue-700"
508
+ onClick={onClick}
509
+ fill="none"
510
+ stroke="currentColor"
511
+ viewBox="0 0 24 24"
512
+ >
513
+ <path
514
+ strokeLinecap="round"
515
+ strokeLinejoin="round"
516
+ strokeWidth={2}
517
+ d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
518
+ />
519
+ </svg>
520
+ ),
521
+ renderModalSearchInput: ({
522
+ searchText,
523
+ setSearchText,
524
+ isLoading,
525
+ placeholder,
526
+ onSearch
527
+ }) => (
528
+ <div className="relative">
529
+ <input
530
+ type="text"
531
+ value={searchText}
532
+ onChange={(e) => setSearchText(e.target.value)}
533
+ onKeyDown={(e) => e.key === 'Enter' && onSearch && onSearch()}
534
+ placeholder={placeholder}
535
+ className="w-full h-10 px-4 pr-20 border-2 border-blue-300 rounded-lg focus:border-blue-500"
536
+ disabled={isLoading}
537
+ />
538
+ {searchText && (
539
+ <button
540
+ onClick={() => setSearchText('')}
541
+ disabled={isLoading}
542
+ className="absolute right-12 top-1/2 -translate-y-1/2 p-2 text-gray-400 hover:text-gray-600"
543
+ >
544
+
545
+ </button>
546
+ )}
547
+ <button
548
+ onClick={onSearch}
549
+ disabled={isLoading}
550
+ className="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-blue-500 hover:text-blue-700"
551
+ >
552
+ 🔍
553
+ </button>
554
+ </div>
555
+ )
556
+ }
557
+ }
558
+ }
559
+ };
560
+ ```
561
+
331
562
  ## Image Cropping with Manual Confirmation
332
563
 
333
564
  The plugin features an advanced image cropping system with manual confirmation for precise control over search queries.
@@ -556,7 +787,18 @@ const settings = {
556
787
  productItem: 'hover:scale-105 transition-all duration-300 shadow-lg',
557
788
  filterSidebar: 'bg-gradient-to-b from-gray-50 to-white',
558
789
  paginationButton: 'rounded-full px-4 py-2 bg-blue-600 text-white',
559
- activeFilterTag: 'bg-blue-100 text-blue-800 px-3 py-1 rounded-full'
790
+ activeFilterTag: 'bg-blue-100 text-blue-800 px-3 py-1 rounded-full',
791
+
792
+ // Advanced crop styling
793
+ cropComponent: 'border-2 border-dashed border-blue-300 rounded-lg',
794
+ cropImage: 'rounded-lg shadow-md',
795
+ cropImageActive: 'brightness-110 contrast-110',
796
+ cropImageNonCropping: 'hover:scale-105 transition-transform',
797
+ cropImageContainer: 'bg-gray-50 rounded-lg p-2',
798
+ cropOverlay: 'backdrop-blur-sm',
799
+ cropOverlayBackground: 'bg-black/60',
800
+ cropSelection: 'border-4 border-blue-500',
801
+ cropSelectionHighlight: 'shadow-2xl shadow-blue-500/50'
560
802
  }
561
803
  };
562
804
  ```
@@ -915,7 +1157,8 @@ export function SiteHeader() {
915
1157
  settings: {
916
1158
  maxFileSize: 5,
917
1159
  customStyles: {
918
- imageSearchModal: 'max-w-lg rounded-xl'
1160
+ imageSearchModal: 'max-w-lg rounded-xl',
1161
+ imageSearchModalOverlay: 'bg-black/70 backdrop-blur-sm' // Custom overlay
919
1162
  }
920
1163
  }
921
1164
  }}
@@ -1430,7 +1673,8 @@ const advancedStylingSettings = {
1430
1673
  imageSearchTipsSection: 'bg-yellow-50 border-l-4 border-yellow-400',
1431
1674
  imageSearchTipsTitle: 'text-yellow-800 font-bold',
1432
1675
  imageSearchTipsList: 'text-yellow-700',
1433
- imageSearchTipsItem: 'hover:text-yellow-900 transition-colors'
1676
+ imageSearchTipsItem: 'hover:text-yellow-900 transition-colors',
1677
+ imageSearchModalOverlay: 'bg-black/60 backdrop-blur-md' // NEW: Custom overlay
1434
1678
  }
1435
1679
  };
1436
1680
  ```
@@ -1487,6 +1731,7 @@ const hybridAdvancedSettings = {
1487
1731
  - `filterSidebar`, `filterSidebarMobileHeader`, `filterGroup`, `filterGroupTitle`, `filterGroupContent`
1488
1732
  - `filterItem`, `filterItemInput`, `filterItemLabel`, `filterItemCount`
1489
1733
  - `imageSection`, `imageContainer`, `imageWrapper`, `cropButton`, `tickButton`, `uploadButton`, `resetButton`, `errorMessage`, `cropControls`
1734
+ - `cropComponent`, `cropImage`, `cropImageActive`, `cropImageNonCropping`, `cropImageContainer`, `cropOverlay`, `cropSelection`, `cropSelectionBorder`, `cropOverlayBackground`, `cropSelectionHighlight`
1490
1735
  - `mobileActiveFilters`, `mobileActiveFilterTag`, `mobileClearAllButton`
1491
1736
 
1492
1737
  **Products & Results:**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinon/pz-similar-products",
3
- "version": "1.92.0-snapshot-ZERO-3457-20250627111231",
3
+ "version": "1.93.0-rc.46",
4
4
  "license": "MIT",
5
5
  "main": "src/index.ts",
6
6
  "peerDependencies": {
@@ -27,9 +27,14 @@ export const similarProductsApi = api.injectEndpoints({
27
27
  endpoints: (build) => ({
28
28
  getSimilarProductsByUrl: build.query<
29
29
  SimilarProductsResponse,
30
- { url: string; limit?: number; excluded_product_ids?: number[] }
30
+ {
31
+ url: string;
32
+ limit?: number;
33
+ excluded_product_ids?: number[];
34
+ text?: string;
35
+ }
31
36
  >({
32
- query: ({ url, limit = 20, excluded_product_ids }) => {
37
+ query: ({ url, limit = 20, excluded_product_ids, text }) => {
33
38
  const params = new URLSearchParams();
34
39
  params.append('limit', String(limit));
35
40
  params.append('url', url);
@@ -38,6 +43,10 @@ export const similarProductsApi = api.injectEndpoints({
38
43
  params.append('excluded_product_ids', excluded_product_ids.join(','));
39
44
  }
40
45
 
46
+ if (text) {
47
+ params.append('text', text);
48
+ }
49
+
41
50
  return {
42
51
  url: `/api/similar-products?${params.toString()}`,
43
52
  method: 'GET',
@@ -50,12 +59,22 @@ export const similarProductsApi = api.injectEndpoints({
50
59
 
51
60
  getSimilarProductsByImage: build.mutation<
52
61
  SimilarProductsResponse,
53
- { image: string; limit?: number; excluded_product_ids?: number[] }
62
+ {
63
+ image: string;
64
+ limit?: number;
65
+ excluded_product_ids?: number[];
66
+ text?: string;
67
+ }
54
68
  >({
55
- query: ({ image, limit = 20, excluded_product_ids }) => {
69
+ query: ({ image, limit = 20, excluded_product_ids, text }) => {
56
70
  const params = new URLSearchParams();
57
71
  params.append('limit', String(limit));
58
72
 
73
+ const bodyData: any = { image, excluded_product_ids };
74
+ if (text) {
75
+ bodyData.text = text;
76
+ }
77
+
59
78
  return {
60
79
  url: `/api/similar-products?${params.toString()}`,
61
80
  method: 'POST',
@@ -63,7 +82,7 @@ export const similarProductsApi = api.injectEndpoints({
63
82
  'Content-Type': 'application/json',
64
83
  Accept: 'application/json'
65
84
  },
66
- body: JSON.stringify({ image, excluded_product_ids })
85
+ body: JSON.stringify(bodyData)
67
86
  };
68
87
  }
69
88
  }),
@@ -72,12 +91,21 @@ export const similarProductsApi = api.injectEndpoints({
72
91
  SimilarProductsListResponse,
73
92
  {
74
93
  filter: string;
75
- searchParams?: Record<string, string>;
94
+ searchParams?: Record<string, string | string[]>;
76
95
  isExclude?: boolean;
77
96
  }
78
97
  >({
79
98
  query: ({ filter, searchParams = {}, isExclude = false }) => {
80
- const params = new URLSearchParams(searchParams);
99
+ const params = new URLSearchParams();
100
+
101
+ Object.entries(searchParams).forEach(([key, value]) => {
102
+ if (Array.isArray(value)) {
103
+ value.forEach((v) => params.append(key, v));
104
+ } else {
105
+ params.append(key, value);
106
+ }
107
+ });
108
+
81
109
  const queryString = params.toString();
82
110
 
83
111
  const headerName = isExclude
@@ -98,7 +126,7 @@ export const similarProductsApi = api.injectEndpoints({
98
126
  .reduce((acc, key) => {
99
127
  acc[key] = searchParams[key];
100
128
  return acc;
101
- }, {} as Record<string, string>);
129
+ }, {} as Record<string, string | string[]>);
102
130
 
103
131
  return JSON.stringify({
104
132
  filter,
@@ -119,4 +147,4 @@ export const {
119
147
  useLazyGetSimilarProductsListQuery
120
148
  } = similarProductsApi;
121
149
 
122
- export type { Product, Facet, FacetChoice, SortOption, Pagination };
150
+ export type { Product, Facet, FacetChoice, SortOption, Pagination };
@@ -1,3 +1,4 @@
1
1
  export { useSimilarProducts } from './use-similar-products';
2
2
  export { useImageCropper } from './use-image-cropper';
3
3
  export { useImageSearchFeature } from './use-image-search-feature';
4
+ export { useTextSearchFeature } from './use-text-search-feature';