@nyris/nyris-webapp 0.3.91 → 0.3.92
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/build/asset-manifest.json +6 -6
- package/build/data/related-parts.json +83 -0
- package/build/index.html +1 -1
- package/build/js/settings.example.js +3 -0
- package/build/static/css/main.5ea01690.css +4 -0
- package/build/static/css/main.5ea01690.css.map +1 -0
- package/build/static/js/main.36b77705.js +3 -0
- package/build/static/js/{main.f2255597.js.map → main.36b77705.js.map} +1 -1
- package/package.json +4 -3
- package/public/data/related-parts.json +83 -0
- package/public/js/settings.example.js +3 -0
- package/src/App.test.tsx +0 -1
- package/src/App.tsx +0 -1
- package/src/assets/arrow_down_expanded.svg +3 -0
- package/src/assets/arrow_enter.svg +3 -0
- package/src/assets/camera.svg +3 -0
- package/src/assets/close.svg +3 -0
- package/src/assets/enter.svg +3 -0
- package/src/assets/refresh.svg +3 -0
- package/src/assets/vizo_avatar.svg +16 -0
- package/src/components/Cadenas/CadenasWebViewer.tsx +1 -1
- package/src/components/Cart.tsx +48 -36
- package/src/components/ChatAssistant/ChatAssistant.tsx +289 -0
- package/src/components/ChatAssistant/MobileChatAssistant.tsx +291 -0
- package/src/components/ChatAssistant/OptionChip.tsx +78 -0
- package/src/components/ChatAssistant/index.ts +3 -0
- package/src/components/ChatAssistant/useChatAssistantLogic.ts +745 -0
- package/src/components/CurrentRefinements.tsx +2 -2
- package/src/components/CustomCameraDrawer.tsx +56 -13
- package/src/components/DragDropFile.tsx +5 -5
- package/src/components/ExperienceVisualSearch/ExperienceVisualSearch.tsx +1 -1
- package/src/components/Header.tsx +116 -96
- package/src/components/Hint.tsx +1 -2
- package/src/components/HitsPerPage.tsx +9 -3
- package/src/components/ImagePreview.tsx +32 -17
- package/src/components/ImageUpload.tsx +16 -8
- package/src/components/Inquiry/InquiryBanner.tsx +1 -1
- package/src/components/Inquiry/InquiryModal.tsx +35 -29
- package/src/components/ItemSpecification.tsx +58 -126
- package/src/components/LocationInfoPopup.tsx +33 -33
- package/src/components/MatchNotificationBanner.tsx +90 -36
- package/src/components/PostFilter/PostFilter.tsx +1 -1
- package/src/components/PostFilter/PostFilterComponent.tsx +0 -1
- package/src/components/PostFilter/PostFilterFindApi.tsx +0 -1
- package/src/components/PoweredBy.tsx +1 -1
- package/src/components/PreFilter/PreFilter.tsx +14 -3
- package/src/components/PreFilter/PreFilterModal.tsx +0 -1
- package/src/components/Product/Product.tsx +15 -11
- package/src/components/Product/ProductAttribute.tsx +4 -5
- package/src/components/Product/ProductDetailViewModal.tsx +2 -4
- package/src/components/Product/ProductList.tsx +26 -13
- package/src/components/Rfq/RfqModal.tsx +1 -1
- package/src/components/SidePanel.tsx +124 -91
- package/src/components/SmartFilter.tsx +320 -0
- package/src/components/TextSearch.tsx +134 -70
- package/src/components/UploadDisclaimer.tsx +1 -1
- package/src/hooks/useBadResultsRecovery.ts +407 -0
- package/src/hooks/useEffectiveGroundingResults.ts +54 -0
- package/src/hooks/useGoodResultsChat.ts +651 -0
- package/src/hooks/useGroundedSearch.ts +88 -0
- package/src/hooks/useImageSearch.ts +139 -187
- package/src/hooks/useResultEvaluator.ts +417 -0
- package/src/index.css +1 -1
- package/src/index.tsx +0 -1
- package/src/layouts/AppLayout.tsx +53 -2
- package/src/pages/Home.tsx +11 -52
- package/src/pages/Login.tsx +1 -2
- package/src/pages/Logout.tsx +1 -1
- package/src/pages/Result.tsx +198 -200
- package/src/providers/AuthProvider.tsx +0 -1
- package/src/services/Feedback.ts +1 -1
- package/src/services/visualSearch.ts +0 -21
- package/src/services/vizo.ts +192 -4
- package/src/stores/chat/chatStore.ts +150 -0
- package/src/stores/chat/conversationStore.ts +300 -0
- package/src/stores/request/Misc/misc.slice.ts +2 -2
- package/src/stores/request/filter/filter.slice.ts +8 -8
- package/src/stores/request/query/query.slice.ts +2 -2
- package/src/stores/request/requestImage/requestImage.slice.ts +6 -6
- package/src/stores/request/specifications/specifications.slice.ts +10 -7
- package/src/stores/result/detectedRegions/detectedRegions.slice.ts +1 -1
- package/src/stores/result/prodcuts/products.initialState.ts +12 -0
- package/src/stores/result/prodcuts/products.slice.ts +28 -8
- package/src/stores/result/session/session.slice.ts +2 -2
- package/src/stores/smartFilters/smartFiltersStore.ts +270 -0
- package/src/stores/types.ts +41 -0
- package/src/stores/ui/ai/ai.initialState.ts +5 -0
- package/src/stores/ui/ai/ai.slice.ts +15 -0
- package/src/stores/ui/banner/banner.initialState.ts +6 -0
- package/src/stores/ui/banner/banner.slice.ts +14 -0
- package/src/stores/ui/feedback/feedback.slice.ts +1 -1
- package/src/stores/ui/loading/loading.slice.ts +4 -4
- package/src/stores/ui/uiStore.ts +7 -1
- package/src/styles/product.scss +0 -2
- package/src/types.ts +3 -7
- package/src/utils/cropImageToBase64.ts +32 -0
- package/src/utils/fetchProductImage.ts +109 -0
- package/src/utils/imageConverters.ts +124 -0
- package/src/utils/relatedParts.ts +35 -0
- package/src/utils/specificationFilter.ts +1 -5
- package/tailwind.config.js +3 -2
- package/build/static/css/main.734b52e1.css +0 -4
- package/build/static/css/main.734b52e1.css.map +0 -1
- package/build/static/js/main.f2255597.js +0 -3
- package/src/utils/addAssets.ts +0 -40
- /package/build/static/js/{main.f2255597.js.LICENSE.txt → main.36b77705.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { memo, useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
import { Sparkles, Send, Loader2, AlertCircle, Globe } from 'lucide-react';
|
|
4
|
+
|
|
5
|
+
import { Icon } from '@nyris/nyris-react-components';
|
|
6
|
+
import useUiStore from 'stores/ui/uiStore';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
|
+
import CustomCamera from 'components/CustomCameraDrawer';
|
|
9
|
+
import ImageUpload from 'components/ImageUpload';
|
|
10
|
+
import OptionChip, { ChatOption } from './OptionChip';
|
|
11
|
+
import { useChatAssistantLogic } from './useChatAssistantLogic';
|
|
12
|
+
|
|
13
|
+
function MobileChatAssistant() {
|
|
14
|
+
const { t } = useTranslation();
|
|
15
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
inputValue,
|
|
19
|
+
setInputValue,
|
|
20
|
+
messages,
|
|
21
|
+
isLoading,
|
|
22
|
+
isEvaluated,
|
|
23
|
+
error,
|
|
24
|
+
hasApiKey,
|
|
25
|
+
p7Running,
|
|
26
|
+
p7Done,
|
|
27
|
+
catalogSearching,
|
|
28
|
+
messagesEndRef,
|
|
29
|
+
imageInputRef,
|
|
30
|
+
handleSendMessage,
|
|
31
|
+
handleOptionClick,
|
|
32
|
+
handleImageUpload,
|
|
33
|
+
} = useChatAssistantLogic();
|
|
34
|
+
|
|
35
|
+
const setIsAiModeOpen = useUiStore(state => state.setIsAiModeOpen);
|
|
36
|
+
|
|
37
|
+
const [isOpenModalCamera, setOpenModalCamera] = useState<boolean>(false);
|
|
38
|
+
|
|
39
|
+
// Focus input on text_search_prompt option click
|
|
40
|
+
const wrappedHandleOptionClick = useCallback(
|
|
41
|
+
async (option: ChatOption) => {
|
|
42
|
+
if (option.action_type === 'text_search_prompt') {
|
|
43
|
+
inputRef.current?.focus();
|
|
44
|
+
}
|
|
45
|
+
if (option.action_type === 'related_part') {
|
|
46
|
+
inputRef.current?.focus();
|
|
47
|
+
}
|
|
48
|
+
await handleOptionClick(option);
|
|
49
|
+
},
|
|
50
|
+
[handleOptionClick],
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div className="fixed inset-x-0 bottom-0 z-[50] flex flex-col justify-end max-h-[50vh]">
|
|
55
|
+
{/* Chat container — anchored to bottom, content-based height, max 50vh */}
|
|
56
|
+
<div
|
|
57
|
+
className={twMerge(
|
|
58
|
+
'relative flex flex-col max-h-[50vh] overflow-hidden bg-white/40 backdrop-blur-[8px] rounded-t-[24px] ',
|
|
59
|
+
'shadow-[0px_0px_32px_0px_rgba(152,155,183,1)]',
|
|
60
|
+
)}
|
|
61
|
+
>
|
|
62
|
+
{/* Close / collapse chevron */}
|
|
63
|
+
<div className="flex items-center justify-end px-4 pt-3 pb-1 absolute top-4 right-4">
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
className="w-8 h-8 flex items-center justify-center rounded-lg bg-[#FAFAFA]"
|
|
67
|
+
onClick={() => setIsAiModeOpen(false)}
|
|
68
|
+
>
|
|
69
|
+
<Icon name="arrow_down" className="fill-[#3B3E5F] w-4 h-4" />
|
|
70
|
+
</button>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
{error && (
|
|
74
|
+
<div className="flex-shrink-0 mx-4 mt-1 p-2.5 bg-red-50 border border-red-200 rounded-lg flex items-center gap-2">
|
|
75
|
+
<AlertCircle size={12} className="text-red-500 flex-shrink-0" />
|
|
76
|
+
<p className="text-[11px] text-red-700">{error}</p>
|
|
77
|
+
</div>
|
|
78
|
+
)}
|
|
79
|
+
|
|
80
|
+
{/* Messages area */}
|
|
81
|
+
<div className="flex-1 min-h-0 overflow-y-auto py-3 space-y-3 px-4">
|
|
82
|
+
{messages.length === 0 && !isLoading ? (
|
|
83
|
+
<div className="flex flex-col items-center justify-center flex-grow text-center px-4 py-10">
|
|
84
|
+
<div className="w-12 h-12 rounded-full bg-[#F0EFFF] flex items-center justify-center mb-3">
|
|
85
|
+
<Sparkles size={20} className="text-[#3E36DC]" />
|
|
86
|
+
</div>
|
|
87
|
+
<p className="text-sm font-semibold text-[#2B2C46] mb-1">
|
|
88
|
+
Hi! I can help you find parts faster. What are you looking for?
|
|
89
|
+
</p>
|
|
90
|
+
<p className="text-[11px] text-[#999] leading-relaxed max-w-[200px]">
|
|
91
|
+
Upload an image to get started, or search for a product
|
|
92
|
+
</p>
|
|
93
|
+
</div>
|
|
94
|
+
) : (
|
|
95
|
+
messages.map((msg, i) => (
|
|
96
|
+
<div
|
|
97
|
+
key={msg.id || i}
|
|
98
|
+
className={twMerge(
|
|
99
|
+
'flex',
|
|
100
|
+
msg.role === 'user' ? 'justify-end' : 'justify-start',
|
|
101
|
+
)}
|
|
102
|
+
>
|
|
103
|
+
<div className="max-w-[85%]">
|
|
104
|
+
<div
|
|
105
|
+
className={twMerge(
|
|
106
|
+
'py-3 px-4 text-sm leading-relaxed',
|
|
107
|
+
msg.role === 'user'
|
|
108
|
+
? 'bg-[#3E36DC] text-white rounded-tl-[16px] rounded-tr-[8px] rounded-br-[16px] rounded-bl-[16px] px-4 py-3 font-medium'
|
|
109
|
+
: msg?.content?.startsWith('[P7')
|
|
110
|
+
? 'bg-[#EEF2FF] border border-[#C7D2FE] text-[#2B2C46] rounded-2xl rounded-bl-sm'
|
|
111
|
+
: 'bg-white text-[#2B2C46] rounded-2xl rounded-bl-sm shadow-sm',
|
|
112
|
+
)}
|
|
113
|
+
>
|
|
114
|
+
{msg.imageUrl && (
|
|
115
|
+
<img
|
|
116
|
+
src={msg.imageUrl}
|
|
117
|
+
alt="Uploaded"
|
|
118
|
+
className="w-[48px] h-[48px] rounded-lg object-cover mb-2"
|
|
119
|
+
/>
|
|
120
|
+
)}
|
|
121
|
+
{msg?.content?.startsWith('[P7') && (
|
|
122
|
+
<div className="flex items-center gap-1 mb-1.5 text-indigo-600 font-semibold text-[10px]">
|
|
123
|
+
<Globe size={10} /> Google Grounding
|
|
124
|
+
</div>
|
|
125
|
+
)}
|
|
126
|
+
<pre className="whitespace-pre-wrap font-sans text-sm leading-5 tracking-[0.16px]">
|
|
127
|
+
{msg?.content?.startsWith('[P7')
|
|
128
|
+
? msg.content.replace(/^\[P7[^\]]*\]\s*/, '')
|
|
129
|
+
: msg.content}
|
|
130
|
+
</pre>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
{msg.role === 'assistant' &&
|
|
134
|
+
msg.options &&
|
|
135
|
+
msg.options.length > 0 && (
|
|
136
|
+
<div className="mt-2 space-y-2.5">
|
|
137
|
+
<div className="flex flex-wrap gap-1.5">
|
|
138
|
+
{msg.options
|
|
139
|
+
.filter(o => o.action_type !== 'text_search_prompt')
|
|
140
|
+
.map((option, optIdx) => (
|
|
141
|
+
<OptionChip
|
|
142
|
+
key={optIdx}
|
|
143
|
+
option={option}
|
|
144
|
+
onClick={wrappedHandleOptionClick}
|
|
145
|
+
disabled={
|
|
146
|
+
isLoading || i !== messages.length - 1
|
|
147
|
+
}
|
|
148
|
+
/>
|
|
149
|
+
))}
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
)}
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
))
|
|
156
|
+
)}
|
|
157
|
+
|
|
158
|
+
{isLoading && (
|
|
159
|
+
<div className="flex justify-start">
|
|
160
|
+
<div className="flex items-center gap-2 px-3 py-2.5 bg-white/80 rounded-2xl rounded-bl-sm shadow-sm">
|
|
161
|
+
<Loader2 size={12} className="animate-spin text-[#3E36DC]" />
|
|
162
|
+
<span className="text-xs text-[#666]">
|
|
163
|
+
{!isEvaluated
|
|
164
|
+
? 'Analyzing results...'
|
|
165
|
+
: catalogSearching
|
|
166
|
+
? 'Refining your search…'
|
|
167
|
+
: 'Thinking...'}
|
|
168
|
+
</span>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
)}
|
|
172
|
+
|
|
173
|
+
<div ref={messagesEndRef} />
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
{/* P7 Grounding status strip */}
|
|
177
|
+
{(p7Running || p7Done) && (
|
|
178
|
+
<div className="flex-shrink-0 px-4 py-1.5 bg-white/60">
|
|
179
|
+
{p7Running ? (
|
|
180
|
+
<span className="flex items-center gap-1.5 text-[10px] text-blue-600">
|
|
181
|
+
<Globe size={10} className="animate-pulse" /> Running Google
|
|
182
|
+
Grounding...
|
|
183
|
+
</span>
|
|
184
|
+
) : (
|
|
185
|
+
<span className="flex items-center gap-1.5 text-[10px] text-blue-500">
|
|
186
|
+
<Globe size={10} /> Google Grounding complete
|
|
187
|
+
</span>
|
|
188
|
+
)}
|
|
189
|
+
</div>
|
|
190
|
+
)}
|
|
191
|
+
|
|
192
|
+
{/* Bottom input bar */}
|
|
193
|
+
<div className="flex-shrink-0 px-3 pb-4 pt-2">
|
|
194
|
+
<form
|
|
195
|
+
onSubmit={e => {
|
|
196
|
+
e.preventDefault();
|
|
197
|
+
handleSendMessage();
|
|
198
|
+
}}
|
|
199
|
+
className="flex items-center gap-2"
|
|
200
|
+
>
|
|
201
|
+
<div
|
|
202
|
+
className={twMerge(
|
|
203
|
+
'flex items-center gap-2 flex-1 h-14',
|
|
204
|
+
'rounded-[32px] border-[2px] border-solid border-[#655EE3] bg-[#F3F4F8] p-2',
|
|
205
|
+
)}
|
|
206
|
+
>
|
|
207
|
+
<button
|
|
208
|
+
type="button"
|
|
209
|
+
className="flex items-center justify-center p-2 rounded-full flex-shrink-0"
|
|
210
|
+
onClick={() => setIsAiModeOpen(false)}
|
|
211
|
+
>
|
|
212
|
+
<Icon
|
|
213
|
+
name="search_ai"
|
|
214
|
+
width={20}
|
|
215
|
+
height={20}
|
|
216
|
+
className="text-[#3B3E5F]"
|
|
217
|
+
/>
|
|
218
|
+
</button>
|
|
219
|
+
<input
|
|
220
|
+
ref={inputRef}
|
|
221
|
+
className="flex-1 min-w-0 bg-transparent outline-none text-sm text-[#2B2C46] placeholder-[#989BB7]"
|
|
222
|
+
placeholder={isLoading ? 'Please wait...' : t('Ask Vizo!')}
|
|
223
|
+
disabled={isLoading}
|
|
224
|
+
value={inputValue}
|
|
225
|
+
onChange={e => setInputValue(e.target.value)}
|
|
226
|
+
onKeyDown={e => {
|
|
227
|
+
if (e.key === 'Enter' && !e.shiftKey && !isLoading) {
|
|
228
|
+
e.preventDefault();
|
|
229
|
+
handleSendMessage();
|
|
230
|
+
}
|
|
231
|
+
}}
|
|
232
|
+
/>
|
|
233
|
+
<button
|
|
234
|
+
type="submit"
|
|
235
|
+
className="flex items-center justify-center w-10 h-10 rounded-full flex-shrink-0 bg-[#FAFAFA]"
|
|
236
|
+
disabled={!inputValue.trim() || isLoading || !hasApiKey}
|
|
237
|
+
>
|
|
238
|
+
<Send
|
|
239
|
+
size={16}
|
|
240
|
+
className={twMerge(
|
|
241
|
+
inputValue.trim() && !isLoading
|
|
242
|
+
? 'text-[#655EE3]'
|
|
243
|
+
: 'text-[#BBBDCF]',
|
|
244
|
+
)}
|
|
245
|
+
/>
|
|
246
|
+
</button>
|
|
247
|
+
</div>
|
|
248
|
+
|
|
249
|
+
<div
|
|
250
|
+
className={twMerge(
|
|
251
|
+
'h-14 min-w-14 flex items-center justify-center rounded-full bg-[#FFFFFF] border border-solid border-[#DDDEE7]',
|
|
252
|
+
'shadow-ds-2',
|
|
253
|
+
)}
|
|
254
|
+
>
|
|
255
|
+
<ImageUpload
|
|
256
|
+
onCameraClick={() => {
|
|
257
|
+
setOpenModalCamera(true);
|
|
258
|
+
}}
|
|
259
|
+
disableDisclaimer={true}
|
|
260
|
+
/>
|
|
261
|
+
</div>
|
|
262
|
+
</form>
|
|
263
|
+
|
|
264
|
+
{/* Hidden file input for image upload */}
|
|
265
|
+
<input
|
|
266
|
+
ref={imageInputRef}
|
|
267
|
+
type="file"
|
|
268
|
+
accept="image/*"
|
|
269
|
+
className="hidden"
|
|
270
|
+
onChange={e => {
|
|
271
|
+
const file = e.target.files?.[0];
|
|
272
|
+
if (file) {
|
|
273
|
+
handleImageUpload(file);
|
|
274
|
+
e.target.value = '';
|
|
275
|
+
}
|
|
276
|
+
}}
|
|
277
|
+
/>
|
|
278
|
+
</div>
|
|
279
|
+
</div>
|
|
280
|
+
<CustomCamera
|
|
281
|
+
show={isOpenModalCamera}
|
|
282
|
+
onClose={() => {
|
|
283
|
+
setOpenModalCamera(s => !s);
|
|
284
|
+
}}
|
|
285
|
+
handleImageUpload={handleImageUpload}
|
|
286
|
+
/>
|
|
287
|
+
</div>
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export default memo(MobileChatAssistant);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { RotateCcw, Search, Wrench } from 'lucide-react';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
|
|
4
|
+
import Tooltip from 'components/Tooltip/TooltipComponent';
|
|
5
|
+
import { Icon } from '@nyris/nyris-react-components';
|
|
6
|
+
|
|
7
|
+
export type ChatOption = {
|
|
8
|
+
action_type: string;
|
|
9
|
+
label: string;
|
|
10
|
+
value?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type OptionChipProps = {
|
|
14
|
+
option: ChatOption;
|
|
15
|
+
onClick: (option: ChatOption) => void | Promise<void>;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function OptionChip({ option, onClick, disabled = false }: OptionChipProps) {
|
|
20
|
+
const isRestoreOriginal = option.action_type === 'restore_original';
|
|
21
|
+
const isFilter = option.action_type === 'filter';
|
|
22
|
+
const isRelatedPart =
|
|
23
|
+
option.action_type === 'related_part' ||
|
|
24
|
+
option.action_type === 'find_related_parts';
|
|
25
|
+
const isCatalogSearchImage = option.action_type === 'catalog_search_image';
|
|
26
|
+
const isCatalogSearchText = option.action_type === 'catalog_search_text';
|
|
27
|
+
const displayText =
|
|
28
|
+
isFilter && option.value?.trim() ? option.value : option.label;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Tooltip content={displayText} disabled={displayText.length <= 32}>
|
|
32
|
+
<button
|
|
33
|
+
onClick={() => onClick(option)}
|
|
34
|
+
disabled={disabled}
|
|
35
|
+
className={twMerge(
|
|
36
|
+
'flex items-center',
|
|
37
|
+
'px-2 py-1.5 text-xs font-medium rounded-full',
|
|
38
|
+
'transition-colors',
|
|
39
|
+
disabled && 'opacity-50 cursor-not-allowed',
|
|
40
|
+
'bg-[#FFFFFF] font-semibold',
|
|
41
|
+
'border border-[#DDDEE7] text-[#767A9F] hover:bg-[#545987] hover:text-[#F3F4F8]',
|
|
42
|
+
'h-8',
|
|
43
|
+
isRelatedPart &&
|
|
44
|
+
'border border-[#E67E22] text-[#E67E22] bg-[#FFF8F0] hover:bg-[#E67E22] hover:text-white',
|
|
45
|
+
(isRestoreOriginal || isCatalogSearchImage || isCatalogSearchText) &&
|
|
46
|
+
'border border-[#C7D2FE] bg-[#EEF2FF] text-[#3E36DC] hover:bg-[#E0E7FF] hover:text-[#2F29B7]',
|
|
47
|
+
)}
|
|
48
|
+
>
|
|
49
|
+
{isCatalogSearchImage && (
|
|
50
|
+
<div className="pr-1 inline ">
|
|
51
|
+
<Icon
|
|
52
|
+
name="camera_simple"
|
|
53
|
+
className="inline shrink-0 w-[12px] h-[12px]"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
)}
|
|
57
|
+
{isCatalogSearchText && (
|
|
58
|
+
<div className="pr-1 inline ">
|
|
59
|
+
<Search size={11} className="inline shrink-0" />
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
{isRestoreOriginal && (
|
|
63
|
+
<div className="pr-1 inline">
|
|
64
|
+
<RotateCcw size={11} className="inline shrink-0" />
|
|
65
|
+
</div>
|
|
66
|
+
)}
|
|
67
|
+
{isRelatedPart && (
|
|
68
|
+
<div className="inline pr-1">
|
|
69
|
+
<Wrench size={11} className="inline shrink-0" />
|
|
70
|
+
</div>
|
|
71
|
+
)}
|
|
72
|
+
<span className="max-line-1 text-start">{displayText}</span>
|
|
73
|
+
</button>
|
|
74
|
+
</Tooltip>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default OptionChip;
|