@akinon/pz-similar-products 1.92.0-snapshot-ZERO-3457-20250627121541 → 1.93.0-rc.47

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,119 @@
1
1
  # @akinon/pz-similar-products
2
2
 
3
- ## 1.92.0-snapshot-ZERO-3457-20250627121541
3
+ ## 1.93.0-rc.47
4
+
5
+ ## 1.93.0-rc.46
6
+
7
+ ### Minor Changes
8
+
9
+ - 54e31792: ZERO-3532: Added customize options to icons
10
+ - 174bf3a5: ZERO-3533: Refactor similar products API endpoints to support array search parameters and improve query handling
11
+ - d8be48fb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
12
+ - 143be2b9: ZERO-3457: Crop styles are customizable and logic improved for rendering similar products modal
13
+ - 8b1d24eb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
14
+ - d99a6a7d: ZERO-3457: Fixed the settings prop and made sure everything is customizable.
15
+ - 59b275ca: ZERO-3532: Pass settings prop to SimilarProductsButton for enhanced functionality
16
+ - d606f4ac: ZERO-3481: Add locale and currency to list endpoint
17
+
18
+ ## 1.92.0-rc.45
19
+
20
+ ## 1.92.0-rc.44
21
+
22
+ ## 1.92.0-rc.43
23
+
24
+ ## 1.92.0-rc.42
25
+
26
+ ### Minor Changes
27
+
28
+ - 54e31792: ZERO-3532: Added customize options to icons
29
+ - 174bf3a5: ZERO-3533: Refactor similar products API endpoints to support array search parameters and improve query handling
30
+ - d8be48fb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
31
+ - 143be2b9: ZERO-3457: Crop styles are customizable and logic improved for rendering similar products modal
32
+ - 8b1d24eb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
33
+ - d99a6a7d: ZERO-3457: Fixed the settings prop and made sure everything is customizable.
34
+ - 59b275ca: ZERO-3532: Pass settings prop to SimilarProductsButton for enhanced functionality
35
+ - d606f4ac: ZERO-3481: Add locale and currency to list endpoint
36
+
37
+ ## 1.92.0-rc.41
38
+
39
+ ## 1.92.0-rc.40
40
+
41
+ ## 1.92.0-rc.39
42
+
43
+ ### Minor Changes
44
+
45
+ - 174bf3a: ZERO-3533: Refactor similar products API endpoints to support array search parameters and improve query handling
46
+
47
+ ## 1.92.0-rc.38
48
+
49
+ ## 1.92.0-rc.37
50
+
51
+ ## 1.92.0-rc.36
52
+
53
+ ## 1.92.0-rc.35
54
+
55
+ ## 1.92.0-rc.34
56
+
57
+ ## 1.92.0-rc.33
58
+
59
+ ### Minor Changes
60
+
61
+ - 59b275c: ZERO-3532: Pass settings prop to SimilarProductsButton for enhanced functionality
62
+
63
+ ## 1.92.0-rc.32
64
+
65
+ ### Minor Changes
66
+
67
+ - 54e3179: ZERO-3532: Added customize options to icons
68
+
69
+ ## 1.92.0-rc.31
70
+
71
+ ## 1.92.0-rc.30
72
+
73
+ ## 1.92.0-rc.29
74
+
75
+ ## 1.92.0-rc.28
76
+
77
+ ## 1.92.0-rc.27
4
78
 
5
79
  ### Minor Changes
6
80
 
7
- - d99a6a7: ZERO-3457_1: Fixed the settings prop and made sure everything is customizable.
81
+ - d606f4a: ZERO-3481: Add locale and currency to list endpoint
82
+
83
+ ## 1.92.0-rc.26
84
+
85
+ ## 1.92.0-rc.25
86
+
87
+ ## 1.92.0-rc.24
88
+
89
+ ## 1.92.0-rc.23
90
+
91
+ ## 1.92.0-rc.22
92
+
93
+ ### Minor Changes
94
+
95
+ - 143be2b: ZERO-3457: Crop styles are customizable and logic improved for rendering similar products modal
96
+
97
+ ## 1.92.0-rc.21
98
+
99
+ ### Minor Changes
100
+
101
+ - d99a6a7: ZERO-3457: Fixed the settings prop and made sure everything is customizable.
102
+
103
+ ## 1.92.0-rc.20
104
+
105
+ ### Minor Changes
106
+
107
+ - 8b1d24e: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
108
+
109
+ ## 1.92.0-rc.19
110
+
111
+ ### Minor Changes
112
+
113
+ - d8be48f: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
114
+
115
+ ## 1.92.0-rc.18
116
+
117
+ ## 1.92.0-rc.17
118
+
119
+ ## 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
@@ -272,6 +378,29 @@ interface SimilarProductsSettings {
272
378
  mobileActiveFilters?: string;
273
379
  mobileActiveFilterTag?: string;
274
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')
275
404
  };
276
405
 
277
406
  // 25+ render functions for granular control
@@ -292,6 +421,8 @@ interface SimilarProductsSettings {
292
421
  renderItemCount?: (props) => React.ReactNode;
293
422
  renderSortDropdown?: (props) => React.ReactNode;
294
423
  renderFilterToggleButton?: (props) => React.ReactNode;
424
+ renderModalSearchInput?: (props) => React.ReactNode;
425
+ renderSearchIcon?: (props) => React.ReactNode;
295
426
  // ... see examples for complete list
296
427
  };
297
428
  filterSidebar?: {
@@ -329,6 +460,105 @@ interface SimilarProductsSettings {
329
460
  }
330
461
  ```
331
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
+
332
562
  ## Image Cropping with Manual Confirmation
333
563
 
334
564
  The plugin features an advanced image cropping system with manual confirmation for precise control over search queries.
@@ -557,7 +787,18 @@ const settings = {
557
787
  productItem: 'hover:scale-105 transition-all duration-300 shadow-lg',
558
788
  filterSidebar: 'bg-gradient-to-b from-gray-50 to-white',
559
789
  paginationButton: 'rounded-full px-4 py-2 bg-blue-600 text-white',
560
- 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'
561
802
  }
562
803
  };
563
804
  ```
@@ -1490,6 +1731,7 @@ const hybridAdvancedSettings = {
1490
1731
  - `filterSidebar`, `filterSidebarMobileHeader`, `filterGroup`, `filterGroupTitle`, `filterGroupContent`
1491
1732
  - `filterItem`, `filterItemInput`, `filterItemLabel`, `filterItemCount`
1492
1733
  - `imageSection`, `imageContainer`, `imageWrapper`, `cropButton`, `tickButton`, `uploadButton`, `resetButton`, `errorMessage`, `cropControls`
1734
+ - `cropComponent`, `cropImage`, `cropImageActive`, `cropImageNonCropping`, `cropImageContainer`, `cropOverlay`, `cropSelection`, `cropSelectionBorder`, `cropOverlayBackground`, `cropSelectionHighlight`
1493
1735
  - `mobileActiveFilters`, `mobileActiveFilterTag`, `mobileClearAllButton`
1494
1736
 
1495
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-20250627121541",
3
+ "version": "1.93.0-rc.47",
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';