@skalfa/skalfa-component 1.0.52 → 1.0.54

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.
@@ -15,6 +15,8 @@ export interface SelectOptionProps {
15
15
  value : string | number;
16
16
  searchable ?: string[];
17
17
  customLabel ?: ReactNode;
18
+ customOption ?: ((option: any) => ReactNode) | ReactNode;
19
+ [key: string] : any;
18
20
  };
19
21
 
20
22
  export interface SelectProps {
@@ -35,7 +37,7 @@ export interface SelectProps {
35
37
 
36
38
  options ?: SelectOptionProps[];
37
39
  searchable ?: boolean;
38
- serverOptionControl ?: ApiType & { cacheName?: string | false };
40
+ serverOptionControl ?: ApiType & { cacheName?: string | boolean; selectableOption?: string[] };
39
41
  idbOptionControl ?: { store: string, labelKey: string, valueKey: string };
40
42
  serverSearchable ?: boolean;
41
43
  includedOptions ?: SelectOptionProps[];
@@ -45,6 +47,8 @@ export interface SelectProps {
45
47
  maxShowOption ?: number;
46
48
  creatable ?: boolean | string;
47
49
  creatableLabel ?: string;
50
+ customOption ?: (option: any) => ReactNode;
51
+ selectableOption ?: string[];
48
52
 
49
53
  onChange ?: (value: any, data?: any) => any;
50
54
  register ?: (name: string, validations?: ValidationRules) => void;
@@ -83,9 +87,11 @@ export function SelectComponent({
83
87
  exceptOptions = [],
84
88
  tempOptions,
85
89
  newOption,
86
- maxShowOption = 10,
90
+ maxShowOption,
87
91
  creatable,
88
92
  creatableLabel,
93
+ customOption,
94
+ selectableOption,
89
95
 
90
96
  register,
91
97
  unregister,
@@ -184,13 +190,27 @@ export function SelectComponent({
184
190
  let newFilteredOptions: SelectOptionProps[] = [];
185
191
 
186
192
  if (searchable && !serverSearchable && dataOptions?.length) {
187
- if (e.target.value) {
188
- newFilteredOptions = dataOptions.filter((Option) => (Option.label as string)?.toLowerCase().indexOf(e.target.value.toLowerCase()) > -1).slice(0, maxShowOption);
193
+ if (e?.target?.value) {
194
+ const val = e.target.value.toLowerCase();
195
+ const matched = dataOptions.filter((opt) => {
196
+ if (opt.searchable?.some((s) => s.toLowerCase().indexOf(val) > -1)) return true;
197
+ if (typeof opt.label === "string" && opt.label.toLowerCase().indexOf(val) > -1) return true;
198
+ if (typeof opt.code === "string" && opt.code.toLowerCase().indexOf(val) > -1) return true;
199
+ if (typeof opt.name === "string" && opt.name.toLowerCase().indexOf(val) > -1) return true;
200
+ return false;
201
+ });
202
+ newFilteredOptions = typeof maxShowOption === "number" && maxShowOption > 0
203
+ ? matched.slice(0, maxShowOption)
204
+ : matched;
189
205
  } else {
190
- newFilteredOptions = dataOptions.slice(0, maxShowOption);
206
+ newFilteredOptions = typeof maxShowOption === "number" && maxShowOption > 0
207
+ ? dataOptions.slice(0, maxShowOption)
208
+ : dataOptions;
191
209
  }
192
210
  } else {
193
- newFilteredOptions = dataOptions || [];
211
+ newFilteredOptions = typeof maxShowOption === "number" && maxShowOption > 0
212
+ ? (dataOptions || []).slice(0, maxShowOption)
213
+ : (dataOptions || []);
194
214
  }
195
215
 
196
216
  setActiveOption(-1);
@@ -251,40 +271,68 @@ export function SelectComponent({
251
271
  const fetchOptions = async () => {
252
272
  setLoadingOption(true);
253
273
 
274
+ const selectableOpt = selectableOption || serverOptionControl?.selectableOption || serverOptionControl?.params?.selectableOption;
275
+
254
276
  const serverControl = {
255
277
  ...serverOptionControl,
256
- params: serverSearchable ? { search: keywordSearch, ...(serverOptionControl?.params || {}) } : (serverOptionControl?.params || {}),
257
- headers: { "X-Option": 1 }
278
+ params: {
279
+ ...(serverOptionControl?.params || {}),
280
+ ...(selectableOpt ? { selectableOption: selectableOpt } : {}),
281
+ ...(serverSearchable ? { search: keywordSearch } : {}),
282
+ },
283
+ headers: { "X-Option": 1, ...(serverOptionControl?.headers || {}) }
258
284
  };
259
285
 
260
- const getCacheOptions = await cavity.get(serverOptionControl?.cacheName || `option_${serverOptionControl?.path}`)
261
- const cacheOptions = (getCacheOptions?.data || []) as SelectOptionProps[];
262
-
263
- if (cacheOptions?.length) {
264
- setDataOptions(
265
- [...cacheOptions, ...includedOptions].filter(
266
- (op: SelectOptionProps) => !exceptOptions?.includes(op.value)
267
- )
268
- );
269
- setLoadingOption(false);
270
- } else {
271
- const mutateOptions = await api(serverControl || {});
272
- setDataOptions(
273
- [...(mutateOptions?.data?.data || []), ...(includedOptions || [])].filter(
286
+ const cacheKey = typeof serverOptionControl?.cacheName === "string" && serverOptionControl.cacheName.trim() !== ""
287
+ ? serverOptionControl.cacheName
288
+ : serverOptionControl?.cacheName === true
289
+ ? `option_${serverOptionControl?.path || serverOptionControl?.url}`
290
+ : null;
291
+
292
+ if (cacheKey) {
293
+ const getCacheOptions = await cavity.get(cacheKey);
294
+ const cacheData = getCacheOptions?.data;
295
+ const cacheOptions = (Array.isArray(cacheData?.data) ? cacheData.data : Array.isArray(cacheData) ? cacheData : []) as SelectOptionProps[];
296
+
297
+ if (cacheOptions?.length) {
298
+ const cached = [...cacheOptions, ...includedOptions].filter(
274
299
  (op: SelectOptionProps) => !exceptOptions?.includes(op.value)
275
- )
276
- );
277
- setShowOption(true);
300
+ );
301
+ setDataOptions(cached);
302
+ setFilteredOptions(typeof maxShowOption === "number" && maxShowOption > 0 ? cached.slice(0, maxShowOption) : cached);
303
+ setLoadingOption(false);
304
+ return;
305
+ }
306
+ }
278
307
 
279
- if(serverOptionControl?.cacheName != false) {
280
- cavity.set({
281
- key: serverOptionControl?.cacheName || `option_${serverOptionControl?.path}`,
282
- data: mutateOptions?.data,
283
- expired: 5,
284
- });
308
+ const mutateOptions = await api(serverControl || {});
309
+ const fetchedData = mutateOptions?.data?.data || mutateOptions?.data || [];
310
+ const optionsData = Array.isArray(fetchedData) ? fetchedData.map((item: any) => {
311
+ if (item && typeof item === "object") {
312
+ return {
313
+ ...item,
314
+ name: item.name ?? item.label,
315
+ label: item.label ?? item.name ?? item.code ?? item.value,
316
+ };
285
317
  }
286
- setLoadingOption(false);
318
+ return item;
319
+ }) : [];
320
+
321
+ const finalOptions = [...optionsData, ...(includedOptions || [])].filter(
322
+ (op: SelectOptionProps) => !exceptOptions?.includes(op.value)
323
+ );
324
+ setDataOptions(finalOptions);
325
+ setFilteredOptions(typeof maxShowOption === "number" && maxShowOption > 0 ? finalOptions.slice(0, maxShowOption) : finalOptions);
326
+ setShowOption(true);
327
+
328
+ if (cacheKey) {
329
+ cavity.set({
330
+ key: cacheKey,
331
+ data: mutateOptions?.data,
332
+ expired: 5,
333
+ });
287
334
  }
335
+ setLoadingOption(false);
288
336
  };
289
337
 
290
338
  const fetchIdbOptions = async () => {
@@ -309,6 +357,7 @@ export function SelectComponent({
309
357
  })
310
358
 
311
359
  setDataOptions(rows);
360
+ setFilteredOptions(typeof maxShowOption === "number" && maxShowOption > 0 ? rows.slice(0, maxShowOption) : rows);
312
361
  setLoadingOption(false);
313
362
  }
314
363
  };
@@ -402,7 +451,8 @@ export function SelectComponent({
402
451
  placeholder={!inputHandler.value || (Array.isArray(inputHandler.value) && !inputHandler.value.length) ? placeholder : ""}
403
452
  disabled={disabled}
404
453
  className={cn(
405
- "input cursor-pointer",
454
+ "input cursor-pointer pr-10",
455
+ clearable && "pr-18",
406
456
  leftIcon && "input-with-left-icon",
407
457
  rightIcon && "input-with-right-icon",
408
458
  isCreatingNew && "pl-[4.8rem]",
@@ -493,22 +543,23 @@ export function SelectComponent({
493
543
  return (
494
544
  <div key={key} className="input-values-item">
495
545
  <span>{dataOptions?.find((option) => option.value == item)?.label}</span>
496
- <Icon
497
- icon="solid/times"
498
- className="input-values-delete"
499
- onClick={() => {
500
- const values = Array().concat(inputHandler.value);
501
- const index = values.findIndex((val: string | number) => val == item);
502
-
503
- inputHandler.setValue(values.filter((_, val) => val != index));
504
-
505
- if (!values.filter((_, val) => val != index)?.length) {
506
- setInputShowValue("");
507
- serverSearchable && setKeyword("");
508
- onChange?.("");
509
- }
510
- }}
511
- />
546
+ <div className="input-values-delete">
547
+ <Icon
548
+ icon="solid/times"
549
+ onClick={() => {
550
+ const values = Array().concat(inputHandler.value);
551
+ const index = values.findIndex((val: string | number) => val == item);
552
+
553
+ inputHandler.setValue(values.filter((_, val) => val != index));
554
+
555
+ if (!values.filter((_, val) => val != index)?.length) {
556
+ setInputShowValue("");
557
+ serverSearchable && setKeyword("");
558
+ onChange?.("");
559
+ }
560
+ }}
561
+ />
562
+ </div>
512
563
  </div>
513
564
  );
514
565
  })}
@@ -650,7 +701,7 @@ export function SelectComponent({
650
701
  return (
651
702
  <li
652
703
  className={cn(
653
- "input-suggest",
704
+ "input-suggest flex items-center",
654
705
  (key == activeOption || selected) && "input-suggest-active",
655
706
  pcn<CT>(className, "suggest-item"),
656
707
  (key == activeOption || selected) && pcn<CT>(className, "suggest-item", "active")
@@ -669,8 +720,11 @@ export function SelectComponent({
669
720
  setIsCreatingNew(false);
670
721
 
671
722
  if (!multiple) {
672
- setInputShowValue(option.label);
673
- serverSearchable && setKeyword(option.label as string);
723
+ const displayLabel = typeof option.label === "string" || typeof option.label === "number"
724
+ ? option.label
725
+ : (option.name || option.code || option.value);
726
+ setInputShowValue(displayLabel);
727
+ serverSearchable && setKeyword(typeof displayLabel === "string" ? displayLabel : "");
674
728
  inputHandler.setValue(option.value);
675
729
  onChange?.(option.value, option);
676
730
  } else {
@@ -700,7 +754,11 @@ export function SelectComponent({
700
754
  className="select-suggest-check"
701
755
  />
702
756
  )}
703
- {option.label}
757
+ {customOption
758
+ ? customOption(option)
759
+ : (option.customOption
760
+ ? (typeof option.customOption === "function" ? option.customOption(option) : option.customOption)
761
+ : (option.customLabel || option.label))}
704
762
  </li>
705
763
  );
706
764
  })}