contentoh-components-library 21.5.91 → 21.5.93
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/dist/components/atoms/GeneralButton/styles.js +1 -1
- package/dist/components/atoms/GeneralInput/index.js +54 -245
- package/dist/components/atoms/GeneralInput/styles.js +3 -7
- package/dist/components/atoms/InputFormatter/index.js +68 -223
- package/dist/components/atoms/InputFormatter/styles.js +4 -20
- package/dist/components/molecules/StatusAsignationInfo/index.js +1 -11
- package/dist/components/molecules/TabsMenu/index.js +12 -13
- package/dist/components/molecules/TagAndInput/index.js +24 -361
- package/dist/components/molecules/TagAndInput/styles.js +2 -2
- package/dist/components/organisms/FullProductNameHeader/index.js +22 -6
- package/dist/components/organisms/InputGroup/index.js +18 -22
- package/dist/components/pages/ProviderProductEdition/index.js +47 -34
- package/dist/components/pages/ProviderProductEdition/utils.js +0 -1
- package/dist/components/pages/RetailerProductEdition/RetailerProductEdition.stories.js +196 -179
- package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.context.js +260 -59
- package/dist/components/pages/RetailerProductEdition/context/reducers/product.js +38 -50
- package/dist/components/pages/RetailerProductEdition/index.js +2234 -1715
- package/dist/components/pages/RetailerProductEdition/styles.js +2 -4
- package/dist/components/pages/RetailerProductEdition/utils.js +2 -251
- package/dist/contexts/AiProductEdition.js +157 -234
- package/package.json +2 -4
- package/src/components/atoms/GeneralButton/styles.js +0 -4
- package/src/components/atoms/GeneralInput/index.js +60 -237
- package/src/components/atoms/GeneralInput/styles.js +0 -81
- package/src/components/atoms/InputFormatter/index.js +51 -200
- package/src/components/atoms/InputFormatter/styles.js +0 -284
- package/src/components/molecules/StatusAsignationInfo/index.js +1 -9
- package/src/components/molecules/TabsMenu/index.js +11 -12
- package/src/components/molecules/TagAndInput/index.js +21 -286
- package/src/components/molecules/TagAndInput/styles.js +17 -59
- package/src/components/organisms/FullProductNameHeader/index.js +28 -4
- package/src/components/organisms/FullTabsMenu/index.js +1 -1
- package/src/components/organisms/InputGroup/index.js +4 -12
- package/src/components/pages/ProviderProductEdition/index.js +69 -51
- package/src/components/pages/ProviderProductEdition/utils.js +2 -2
- package/src/components/pages/RetailerProductEdition/RetailerProductEdition.stories.js +224 -201
- package/src/components/pages/RetailerProductEdition/index.js +1718 -1546
- package/src/components/pages/RetailerProductEdition/styles.js +2 -67
- package/src/components/pages/RetailerProductEdition/utils.js +0 -240
- package/dist/ai/utils/compare-strings.js +0 -45
- package/dist/components/organisms/ChangeStatusModal/index.js +0 -531
- package/dist/components/organisms/ChangeStatusModal/styles.js +0 -85
- package/dist/global-files/statusDictionary.js +0 -103
- package/src/ai/utils/compare-strings.js +0 -45
- package/src/assets/images/Icons/arrow.png +0 -0
- package/src/assets/images/Icons/cancel.png +0 -0
- package/src/assets/images/Icons/ia-icon.png +0 -0
- package/src/assets/images/Icons/loading.svg +0 -5
- package/src/assets/images/Icons/reload.png +0 -0
- package/src/components/atoms/RetailerSelector/RetailerSelector.stories.js +0 -10
- package/src/components/atoms/RetailerSelector/index.js +0 -3
- package/src/components/atoms/RetailerSelector/styles.js +0 -0
- package/src/components/organisms/ChangeStatusModal/index.jsx +0 -488
- package/src/components/organisms/ChangeStatusModal/styles.js +0 -333
- package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx +0 -575
- package/src/components/pages/RetailerProductEdition/context/provider-product-edition.reducer.js +0 -62
- package/src/components/pages/RetailerProductEdition/context/reducers/active-state.js +0 -344
- package/src/components/pages/RetailerProductEdition/context/reducers/inputs.js +0 -155
- package/src/components/pages/RetailerProductEdition/context/reducers/product.js +0 -114
- package/src/components/pages/RetailerProductEdition/context/reducers/system.js +0 -60
- package/src/components/pages/RetailerProductEdition/index_old.js +0 -1979
- package/src/components/pages/RetailerProductEdition/stories/Auditor.stories.js +0 -101
- package/src/components/pages/RetailerProductEdition/stories/ImageEditor.stories.js +0 -115
- package/src/components/pages/RetailerProductEdition/stories/TextEditor.stories.js +0 -174
- package/src/contexts/AiProductEdition.jsx +0 -344
- package/src/global-files/statusDictionary.js +0 -103
|
@@ -3,16 +3,6 @@ import { Container } from "./styles";
|
|
|
3
3
|
import { InputFormatter } from "../InputFormatter";
|
|
4
4
|
import { CheckBox } from "../CheckBox";
|
|
5
5
|
|
|
6
|
-
import AiGenerationIcon from "../../../assets/images/Icons/ia-icon.png";
|
|
7
|
-
import LoadingIcon from "../../../assets/images/Icons/loading.svg";
|
|
8
|
-
import ArrowIcon from "../../../assets/images/Icons/arrow.png";
|
|
9
|
-
import CancelIcon from "../../../assets/images/Icons/cancel.png";
|
|
10
|
-
import ReloadIcon from "../../../assets/images/Icons/reload.png";
|
|
11
|
-
|
|
12
|
-
import { useAiProductEdition } from "../../../contexts/AiProductEdition";
|
|
13
|
-
import { InputContainer, BottomContainer, OptionsContainer, ButtonsContainer } from "../InputFormatter/styles";
|
|
14
|
-
import { getTextSimilarityPercentage } from "../../../ai/utils/compare-strings";
|
|
15
|
-
|
|
16
6
|
export const GeneralInput = ({
|
|
17
7
|
inputType,
|
|
18
8
|
inputId,
|
|
@@ -37,67 +27,45 @@ export const GeneralInput = ({
|
|
|
37
27
|
disabled,
|
|
38
28
|
onKeyDown,
|
|
39
29
|
auditClass,
|
|
40
|
-
|
|
41
|
-
//AI Generation
|
|
42
|
-
hasAiGeneration = false,
|
|
43
|
-
isBenefitInput = false,
|
|
44
|
-
isAiGenerationLoading = false,
|
|
45
|
-
isAiRegenerationLoading=false,
|
|
46
|
-
isAiActive = false,
|
|
47
|
-
isAiAvailable = false,
|
|
48
|
-
aiGenerated = false,
|
|
49
|
-
|
|
50
|
-
setIsAiActive = () => {},
|
|
51
|
-
handlerAiGeneration = () => {},
|
|
52
|
-
handlerRegenerateSuggestions = () => {},
|
|
53
|
-
handleChangeSuggestion = () => {}
|
|
54
|
-
|
|
55
30
|
}) => {
|
|
56
|
-
|
|
57
|
-
const {
|
|
58
|
-
suggestions,
|
|
59
|
-
currentSuggestion,
|
|
60
|
-
setCurrentSuggestionValue
|
|
61
|
-
} = useAiProductEdition();
|
|
62
|
-
|
|
63
31
|
const [textValue, setTextValue] = useState({
|
|
64
32
|
value: inputValue,
|
|
65
33
|
});
|
|
66
34
|
const [requiredEmpty, setRequiredEmpty] = useState(false);
|
|
67
35
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
36
|
+
const onHandleChange = (evt) => {
|
|
37
|
+
if (validateInput) {
|
|
38
|
+
setTextValue({ value: validateInput(evt, position, inputsArray) });
|
|
39
|
+
} else if (
|
|
40
|
+
updatedDatasheets ||
|
|
41
|
+
updatedDescriptions ||
|
|
42
|
+
inputType === "textarea"
|
|
43
|
+
) {
|
|
44
|
+
let generalValue;
|
|
45
|
+
if (optionList?.length > 0) {
|
|
46
|
+
let valueSelected = evt.target.value;
|
|
47
|
+
generalValue = valueSelected;
|
|
48
|
+
setTextValue({ value: generalValue });
|
|
49
|
+
} else {
|
|
50
|
+
generalValue =
|
|
51
|
+
inputType === "checkbox" ? evt.target.checked : evt.target.value;
|
|
52
|
+
setTextValue({
|
|
53
|
+
value: generalValue,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
let dataSave = updatedDatasheets?.slice();
|
|
82
57
|
|
|
83
58
|
if (dataSave?.length > 0) {
|
|
84
59
|
const index = dataSave.findIndex((e) => e.attributeId === inputId);
|
|
85
60
|
if (index !== -1) {
|
|
86
|
-
if (generalValue !== inputValue)
|
|
87
|
-
|
|
88
|
-
dataSave[index].aiSuggestionAccepted = generatedWithAi;
|
|
89
|
-
} else {
|
|
90
|
-
dataSave.splice(index, 1);
|
|
91
|
-
}
|
|
61
|
+
if (generalValue !== inputValue) dataSave[index].value = generalValue;
|
|
62
|
+
else dataSave.splice(index, 1);
|
|
92
63
|
} else {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
aiSuggestionAccepted: generatedWithAi,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
64
|
+
dataSave.push({
|
|
65
|
+
articleId: articleId,
|
|
66
|
+
attributeId: inputId,
|
|
67
|
+
value: generalValue,
|
|
68
|
+
});
|
|
101
69
|
}
|
|
102
70
|
} else {
|
|
103
71
|
if (generalValue !== inputValue) {
|
|
@@ -105,69 +73,16 @@ export const GeneralInput = ({
|
|
|
105
73
|
articleId: articleId,
|
|
106
74
|
attributeId: inputId,
|
|
107
75
|
value: generalValue,
|
|
108
|
-
aiSuggestionAccepted: generatedWithAi,
|
|
109
76
|
});
|
|
110
77
|
}
|
|
111
78
|
}
|
|
112
|
-
|
|
113
79
|
setUpdatedDatasheets(dataSave);
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const onHandleChange = (evt) => {
|
|
118
|
-
if (validateInput) {
|
|
119
|
-
setTextValue({ value: validateInput(evt, position, inputsArray) });
|
|
120
|
-
} else if (
|
|
121
|
-
updatedDatasheets ||
|
|
122
|
-
updatedDescriptions ||
|
|
123
|
-
inputType === "textarea"
|
|
124
|
-
) {
|
|
125
|
-
let generalValue;
|
|
126
|
-
if (optionList?.length > 0) {
|
|
127
|
-
generalValue = evt.target.value;
|
|
128
|
-
} else {
|
|
129
|
-
generalValue =
|
|
130
|
-
inputType === "checkbox" ? evt.target.checked : evt.target.value;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
updateParentData(generalValue, aiSuggestionAccepted);
|
|
134
|
-
|
|
135
80
|
} else {
|
|
136
81
|
setTextValue({ value: evt.target.value });
|
|
137
82
|
inputOnChange && inputOnChange(evt);
|
|
138
83
|
}
|
|
139
84
|
};
|
|
140
85
|
|
|
141
|
-
useEffect(() => {
|
|
142
|
-
|
|
143
|
-
if(Object.keys(suggestions).length === 0) return;
|
|
144
|
-
|
|
145
|
-
if(currentSuggestion?.[inputId]) return
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const firstSuggestion = suggestions?.[inputId]?.[0];
|
|
149
|
-
|
|
150
|
-
if(!firstSuggestion) return;
|
|
151
|
-
|
|
152
|
-
setCurrentSuggestionValue({
|
|
153
|
-
inputId,
|
|
154
|
-
index: 0,
|
|
155
|
-
value: firstSuggestion?.value
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
}, [suggestions]);
|
|
159
|
-
|
|
160
|
-
useEffect(() => {
|
|
161
|
-
if(!isAiActive) return;
|
|
162
|
-
setAiSuggestionAccepted(false);
|
|
163
|
-
}, [isAiActive]);
|
|
164
|
-
|
|
165
|
-
useEffect(() => {
|
|
166
|
-
if(!isAiActive && !aiSuggestionAccepted) {
|
|
167
|
-
setTextValue({ value: valueAccepted });
|
|
168
|
-
}
|
|
169
|
-
}, [suggestions, isAiActive]);
|
|
170
|
-
|
|
171
86
|
useEffect(() => {
|
|
172
87
|
setRequiredEmpty(
|
|
173
88
|
isRequired &&
|
|
@@ -175,26 +90,14 @@ export const GeneralInput = ({
|
|
|
175
90
|
);
|
|
176
91
|
}, [textValue]);
|
|
177
92
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
//AI Generation
|
|
188
|
-
|
|
189
|
-
const handleAcceptSuggestion = (suggestionValue) => {
|
|
190
|
-
if(!suggestionValue) return;
|
|
191
|
-
|
|
192
|
-
setValueAccepted(suggestionValue);
|
|
193
|
-
setAiSuggestionAccepted(true);
|
|
194
|
-
setIsAiActive(false);
|
|
195
|
-
|
|
196
|
-
updateParentData(suggestionValue, true, suggestionValue);
|
|
197
|
-
}
|
|
93
|
+
const numberInputOnWheelPreventChange = (e) => {
|
|
94
|
+
// Prevent the input value change
|
|
95
|
+
e.target.blur();
|
|
96
|
+
// Prevent the page/container scrolling
|
|
97
|
+
e.stopPropagation();
|
|
98
|
+
// Refocus immediately, on the next tick (after the current function is done)
|
|
99
|
+
setTimeout(() => e.target.focus(), 0);
|
|
100
|
+
};
|
|
198
101
|
|
|
199
102
|
return (
|
|
200
103
|
<Container isRequired={requiredEmpty} className={auditClass}>
|
|
@@ -221,113 +124,33 @@ export const GeneralInput = ({
|
|
|
221
124
|
disabled={disabled}
|
|
222
125
|
/>
|
|
223
126
|
) : inputType !== "textarea" ? (
|
|
224
|
-
<
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
required={isRequired}
|
|
239
|
-
onKeyDown={onKeyDown}
|
|
240
|
-
// onWheel={numberInputOnWheelPreventChange}
|
|
241
|
-
/>
|
|
242
|
-
{
|
|
243
|
-
|
|
244
|
-
hasAiGeneration && isBenefitInput && (
|
|
245
|
-
<div className={`icon_container ${isAiAvailable ? "ai-available" : ''} ${isAiActive ? 'ai-active' : ''}`} title={!isAiAvailable ? 'Debes de completar ficha técnica e imágenes para desbloquear la generación con IA' : ''} onClick={() => {
|
|
246
|
-
handlerAiGeneration({ type: "attribute" })
|
|
247
|
-
}}>
|
|
248
|
-
<img className={`${isAiGenerationLoading ? 'loading' : ''}`} src={isAiGenerationLoading ? LoadingIcon : isAiActive ? CancelIcon : AiGenerationIcon} />
|
|
249
|
-
</div>
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
</InputContainer>
|
|
254
|
-
<BottomContainer className={isAiActive ? "with-ai" : ""}>
|
|
255
|
-
{
|
|
256
|
-
isAiActive && (
|
|
257
|
-
<div className="ai-options">
|
|
258
|
-
|
|
259
|
-
<OptionsContainer>
|
|
260
|
-
<div className={
|
|
261
|
-
`arrow ${currentSuggestion?.[inputId]?.index === 0 && "disabled"}`
|
|
262
|
-
} onClick={() => {
|
|
263
|
-
handleChangeSuggestion({ action: "prev" })
|
|
264
|
-
}}>
|
|
265
|
-
<img src={ArrowIcon} alt="" />
|
|
266
|
-
</div>
|
|
267
|
-
<p>
|
|
268
|
-
{(currentSuggestion?.[inputId]?.index + 1) || 1}
|
|
269
|
-
/
|
|
270
|
-
{suggestions?.[inputId]?.length}
|
|
271
|
-
</p>
|
|
272
|
-
<div className={`arrow right ${currentSuggestion?.[inputId]?.index === suggestions?.[inputId]?.length - 1 && "disabled"}`} onClick={() => {
|
|
273
|
-
|
|
274
|
-
}}>
|
|
275
|
-
<img onClick={() => {
|
|
276
|
-
handleChangeSuggestion({ action: "next" })
|
|
277
|
-
}} src={ArrowIcon} alt="ai icon" />
|
|
278
|
-
</div>
|
|
279
|
-
</OptionsContainer>
|
|
280
|
-
|
|
281
|
-
<ButtonsContainer>
|
|
282
|
-
|
|
283
|
-
<div className={`reload-suggestions ${isAiRegenerationLoading && "loading"}`} onClick={() => {
|
|
284
|
-
handlerRegenerateSuggestions({
|
|
285
|
-
type: "attribute"
|
|
286
|
-
});
|
|
287
|
-
}}>
|
|
288
|
-
<img className="" src={isAiRegenerationLoading ? LoadingIcon : ReloadIcon} />
|
|
289
|
-
</div>
|
|
290
|
-
|
|
291
|
-
<div className="accept-suggestion" onClick={() => {
|
|
292
|
-
handleAcceptSuggestion(currentSuggestion?.[inputId]?.value);
|
|
293
|
-
}}>
|
|
294
|
-
<p>Aceptar sugerencia</p>
|
|
295
|
-
</div>
|
|
296
|
-
|
|
297
|
-
</ButtonsContainer>
|
|
298
|
-
|
|
299
|
-
</div>
|
|
300
|
-
)
|
|
301
|
-
}
|
|
302
|
-
</BottomContainer>
|
|
303
|
-
</div>
|
|
127
|
+
<input
|
|
128
|
+
type={inputType}
|
|
129
|
+
disabled={disabled}
|
|
130
|
+
id={inputId}
|
|
131
|
+
size={inputSize}
|
|
132
|
+
className="general-input"
|
|
133
|
+
placeholder={inputPlaceholder}
|
|
134
|
+
value={textValue.value}
|
|
135
|
+
onInput={(e) => onHandleChange(e)}
|
|
136
|
+
maxLength={maxChar}
|
|
137
|
+
required={isRequired}
|
|
138
|
+
onKeyDown={onKeyDown}
|
|
139
|
+
onWheel={numberInputOnWheelPreventChange}
|
|
140
|
+
/>
|
|
304
141
|
) : (
|
|
305
142
|
<InputFormatter
|
|
306
143
|
name={inputName}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
hasAiGeneration={hasAiGeneration && inputId != 'commentary-box'}
|
|
318
|
-
isAiAvailable={isAiAvailable}
|
|
319
|
-
aiGenerated={aiGenerated}
|
|
320
|
-
handlerAiGeneration={() => {
|
|
321
|
-
handlerAiGeneration({ type: "description" })
|
|
322
|
-
}}
|
|
323
|
-
handlerRegenerateSuggestions={() => {
|
|
324
|
-
handlerRegenerateSuggestions({ type: "description" })
|
|
325
|
-
}}
|
|
326
|
-
handleChangeSuggestion={handleChangeSuggestion}
|
|
327
|
-
isAiGenerationLoading={isAiGenerationLoading}
|
|
328
|
-
isAiRegenerationLoading={isAiRegenerationLoading}
|
|
329
|
-
isAiActive={isAiActive}
|
|
330
|
-
setIsAiActive={setIsAiActive}
|
|
144
|
+
inputId={inputId}
|
|
145
|
+
placeholder={inputPlaceholder}
|
|
146
|
+
mainValue={textValue.value}
|
|
147
|
+
onChange={onHandleChange}
|
|
148
|
+
articleId={articleId}
|
|
149
|
+
updatedDescriptions={updatedDescriptions}
|
|
150
|
+
setUpdatedDescriptions={setUpdatedDescriptions}
|
|
151
|
+
maxChar={maxChar}
|
|
152
|
+
isRequired={isRequired}
|
|
153
|
+
disabled={disabled}
|
|
331
154
|
/>
|
|
332
155
|
)}
|
|
333
156
|
{/* <p>{description}</p> */}
|
|
@@ -84,84 +84,3 @@ export const Container = styled.div`
|
|
|
84
84
|
background: lightgray;
|
|
85
85
|
}
|
|
86
86
|
`;
|
|
87
|
-
|
|
88
|
-
export const InputContainer = styled.div`
|
|
89
|
-
|
|
90
|
-
&.ai-generation {
|
|
91
|
-
position: relative;
|
|
92
|
-
|
|
93
|
-
cursor: pointer;
|
|
94
|
-
|
|
95
|
-
.ia-input {
|
|
96
|
-
padding-right: 2.5rem;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.icon_container {
|
|
100
|
-
position: absolute;
|
|
101
|
-
right: 10px;
|
|
102
|
-
top: 50%;
|
|
103
|
-
transform: translateY(-50%);
|
|
104
|
-
width: 20px;
|
|
105
|
-
height: 20px;
|
|
106
|
-
padding: 4px;
|
|
107
|
-
|
|
108
|
-
border-radius: 50%;
|
|
109
|
-
overflow: hidden;
|
|
110
|
-
display: flex;
|
|
111
|
-
align-items: center;
|
|
112
|
-
justify-content: center;
|
|
113
|
-
z-index: 1;
|
|
114
|
-
|
|
115
|
-
&::before {
|
|
116
|
-
content: '';
|
|
117
|
-
position: absolute;
|
|
118
|
-
top: 0;
|
|
119
|
-
left: 0;
|
|
120
|
-
width: 100%;
|
|
121
|
-
height: 100%;
|
|
122
|
-
|
|
123
|
-
background: linear-gradient(
|
|
124
|
-
120deg,
|
|
125
|
-
#ffffff 10%,
|
|
126
|
-
#ffe0f4 50%,
|
|
127
|
-
#ffffff 90%
|
|
128
|
-
);
|
|
129
|
-
background-size: 200% 200%;
|
|
130
|
-
|
|
131
|
-
animation: ai-shimmer 3s ease-in-out infinite alternate;
|
|
132
|
-
z-index: -1;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
&.ai-available::before{
|
|
136
|
-
|
|
137
|
-
background: gray;
|
|
138
|
-
background-size: 200% 200%;
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
img {
|
|
143
|
-
width: 100%;
|
|
144
|
-
height: 100%;
|
|
145
|
-
object-fit: contain;
|
|
146
|
-
position: relative;
|
|
147
|
-
z-index: 2;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
img.loading {
|
|
151
|
-
width: 20px;
|
|
152
|
-
height: 20px;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
@keyframes ai-shimmer {
|
|
159
|
-
0% {
|
|
160
|
-
background-position: 0% 50%;
|
|
161
|
-
}
|
|
162
|
-
100% {
|
|
163
|
-
background-position: 100% 50%;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
`;
|