aport-tools 4.2.0 → 4.2.2
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/forms/InputList.d.ts +84 -0
- package/dist/forms/index.d.ts +1 -0
- package/dist/index.esm.js +225 -19
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +223 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
@@ -0,0 +1,84 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
interface Option {
|
3
|
+
id: number | string;
|
4
|
+
label: string;
|
5
|
+
value: any;
|
6
|
+
}
|
7
|
+
interface InputListProps {
|
8
|
+
name: string;
|
9
|
+
/**
|
10
|
+
* Placeholder text displayed in the input box when no selection is made.
|
11
|
+
* @type {string}
|
12
|
+
* @default "Choose value/s"
|
13
|
+
*/
|
14
|
+
placeholder?: string;
|
15
|
+
/**
|
16
|
+
* Custom styles for the component.
|
17
|
+
* @type {object}
|
18
|
+
*/
|
19
|
+
style?: object;
|
20
|
+
/**
|
21
|
+
* Array of options to display in the dropdown. Each option should have an id, label, and value.
|
22
|
+
* @type {Option[]}
|
23
|
+
*/
|
24
|
+
options: Option[];
|
25
|
+
/**
|
26
|
+
* Enables multi-selection mode when true. If enabled, users can select multiple values.
|
27
|
+
* @type {boolean}
|
28
|
+
* @default false
|
29
|
+
*/
|
30
|
+
multi?: boolean;
|
31
|
+
/**
|
32
|
+
* Disables the dropdown input when true.
|
33
|
+
* @type {boolean}
|
34
|
+
* @default false
|
35
|
+
*/
|
36
|
+
disabled?: boolean;
|
37
|
+
/**
|
38
|
+
* Key used to sort options in the dropdown (e.g., by 'id', 'label').
|
39
|
+
* @type {keyof Option}
|
40
|
+
*/
|
41
|
+
sortBy?: keyof Option;
|
42
|
+
/**
|
43
|
+
* If true, displays a separator line between each option.
|
44
|
+
* @type {boolean}
|
45
|
+
* @default false
|
46
|
+
*/
|
47
|
+
separator?: boolean;
|
48
|
+
/**
|
49
|
+
* Closes the dropdown if the user scrolls the list.
|
50
|
+
* @type {boolean}
|
51
|
+
* @default false
|
52
|
+
*/
|
53
|
+
closeOnScroll?: boolean;
|
54
|
+
/**
|
55
|
+
* Closes the dropdown after selecting an item if true (only relevant when multi is false).
|
56
|
+
* @type {boolean}
|
57
|
+
* @default true
|
58
|
+
*/
|
59
|
+
closeOnSelect?: boolean;
|
60
|
+
/**
|
61
|
+
* Limits the maximum number of items that can be selected when multi is true.
|
62
|
+
* Once the limit is reached, the dropdown closes, and no further selections can be made until
|
63
|
+
* an item is deselected.
|
64
|
+
* @type {number}
|
65
|
+
*/
|
66
|
+
maxSelection?: number;
|
67
|
+
}
|
68
|
+
/**
|
69
|
+
* InputList component - A custom dropdown list component for React Native with multi-selection support,
|
70
|
+
* customizable styling, sorting, and configurable close behavior on selection or scrolling.
|
71
|
+
*
|
72
|
+
* @param {string} placeholder - Placeholder text for the input.
|
73
|
+
* @param {object} style - Custom styles for the component.
|
74
|
+
* @param {Option[]} options - Array of options to display in the dropdown.
|
75
|
+
* @param {boolean} multi - Enables multi-selection mode.
|
76
|
+
* @param {boolean} disabled - Disables the dropdown input.
|
77
|
+
* @param {keyof Option} sortBy - Key to sort options by (e.g., 'id').
|
78
|
+
* @param {boolean} separator - If true, adds a separator line between options.
|
79
|
+
* @param {boolean} closeOnScroll - Closes the dropdown if the user scrolls the list.
|
80
|
+
* @param {boolean} closeOnSelect - Closes the dropdown on selection in single-select mode.
|
81
|
+
* @param {number} maxSelection - Maximum number of items selectable in multi-select mode.
|
82
|
+
*/
|
83
|
+
export declare const InputList: React.FC<InputListProps>;
|
84
|
+
export {};
|
package/dist/forms/index.d.ts
CHANGED
package/dist/index.esm.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
/*! aport-tools v4.2.
|
2
|
-
import React, { useContext, useState, createContext, useMemo } from 'react';
|
3
|
-
import { StyleSheet, Text as Text$1, View, TextInput, TouchableOpacity, ActivityIndicator, Platform } from 'react-native';
|
1
|
+
/*! aport-tools v4.2.2 | ISC */
|
2
|
+
import React, { useContext, useState, createContext, useCallback, useMemo } from 'react';
|
3
|
+
import { StyleSheet, Text as Text$1, View, TextInput, TouchableOpacity, Modal, Pressable, FlatList, Keyboard, ActivityIndicator, Platform } from 'react-native';
|
4
4
|
import { ThemeContext } from 'aport-themes';
|
5
5
|
|
6
6
|
/******************************************************************************
|
@@ -81,6 +81,16 @@ function __generator(thisArg, body) {
|
|
81
81
|
}
|
82
82
|
}
|
83
83
|
|
84
|
+
function __spreadArray(to, from, pack) {
|
85
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
86
|
+
if (ar || !(i in from)) {
|
87
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
88
|
+
ar[i] = from[i];
|
89
|
+
}
|
90
|
+
}
|
91
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
92
|
+
}
|
93
|
+
|
84
94
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
85
95
|
var e = new Error(message);
|
86
96
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
@@ -220,23 +230,23 @@ var ErrorList = function ErrorList(_a) {
|
|
220
230
|
var theme = useContext(ThemeContext).theme;
|
221
231
|
var colors = theme.colors;
|
222
232
|
return /*#__PURE__*/React.createElement(View, {
|
223
|
-
style: styles$
|
233
|
+
style: styles$6.container
|
224
234
|
}, errors.map(function (error, index) {
|
225
235
|
return /*#__PURE__*/React.createElement(View, {
|
226
236
|
key: index,
|
227
|
-
style: styles$
|
237
|
+
style: styles$6.errorItem
|
228
238
|
}, /*#__PURE__*/React.createElement(Text, {
|
229
|
-
style: [styles$
|
239
|
+
style: [styles$6.bullet, {
|
230
240
|
color: colors.error.hex
|
231
241
|
}]
|
232
242
|
}, "\u2022"), /*#__PURE__*/React.createElement(Text, {
|
233
|
-
style: [styles$
|
243
|
+
style: [styles$6.errorText, {
|
234
244
|
color: colors.error.hex
|
235
245
|
}]
|
236
246
|
}, error));
|
237
247
|
}));
|
238
248
|
};
|
239
|
-
var styles$
|
249
|
+
var styles$6 = StyleSheet.create({
|
240
250
|
container: {
|
241
251
|
marginTop: 4
|
242
252
|
},
|
@@ -314,13 +324,13 @@ var Input = function Input(_a) {
|
|
314
324
|
setFormValue(name, formattedText);
|
315
325
|
};
|
316
326
|
return /*#__PURE__*/React.createElement(View, {
|
317
|
-
style: styles$
|
327
|
+
style: styles$5.container
|
318
328
|
}, /*#__PURE__*/React.createElement(Text, {
|
319
|
-
style: [styles$
|
329
|
+
style: [styles$5.label, {
|
320
330
|
color: colors.text.hex
|
321
331
|
}]
|
322
332
|
}, label), /*#__PURE__*/React.createElement(TextInput, __assign({
|
323
|
-
style: [styles$
|
333
|
+
style: [styles$5.input, {
|
324
334
|
backgroundColor: colors.body.hex,
|
325
335
|
borderColor: formErrors[name] ? colors.error.hex : "#CCC",
|
326
336
|
color: colors.text.hex
|
@@ -333,7 +343,7 @@ var Input = function Input(_a) {
|
|
333
343
|
errors: formErrors[name]
|
334
344
|
})));
|
335
345
|
};
|
336
|
-
var styles$
|
346
|
+
var styles$5 = StyleSheet.create({
|
337
347
|
container: {
|
338
348
|
marginBottom: 16
|
339
349
|
},
|
@@ -364,11 +374,11 @@ var TextArea = function TextArea(_a) {
|
|
364
374
|
setFormValue(name, text);
|
365
375
|
};
|
366
376
|
return /*#__PURE__*/React.createElement(View, {
|
367
|
-
style: styles$
|
377
|
+
style: styles$4.container
|
368
378
|
}, /*#__PURE__*/React.createElement(Text, {
|
369
|
-
style: styles$
|
379
|
+
style: styles$4.label
|
370
380
|
}, label), /*#__PURE__*/React.createElement(TextInput, __assign({
|
371
|
-
style: [styles$
|
381
|
+
style: [styles$4.textArea, style],
|
372
382
|
value: formValues[name] || '',
|
373
383
|
onChangeText: handleChange,
|
374
384
|
placeholder: label,
|
@@ -381,7 +391,7 @@ var TextArea = function TextArea(_a) {
|
|
381
391
|
errors: formErrors[name]
|
382
392
|
})));
|
383
393
|
};
|
384
|
-
var styles$
|
394
|
+
var styles$4 = StyleSheet.create({
|
385
395
|
container: {
|
386
396
|
marginBottom: 16
|
387
397
|
},
|
@@ -410,18 +420,214 @@ var Label = function Label(_a) {
|
|
410
420
|
var theme = useContext(ThemeContext).theme;
|
411
421
|
var colors = theme.colors;
|
412
422
|
return /*#__PURE__*/React.createElement(Text, {
|
413
|
-
style: [styles$
|
423
|
+
style: [styles$3.label, style, {
|
414
424
|
color: colors.text.hex
|
415
425
|
}]
|
416
426
|
}, text);
|
417
427
|
};
|
418
|
-
var styles$
|
428
|
+
var styles$3 = StyleSheet.create({
|
419
429
|
label: {
|
420
430
|
marginBottom: 4,
|
421
431
|
fontWeight: '500'
|
422
432
|
}
|
423
433
|
});
|
424
434
|
|
435
|
+
/**
|
436
|
+
* InputList component - A custom dropdown list component for React Native with multi-selection support,
|
437
|
+
* customizable styling, sorting, and configurable close behavior on selection or scrolling.
|
438
|
+
*
|
439
|
+
* @param {string} placeholder - Placeholder text for the input.
|
440
|
+
* @param {object} style - Custom styles for the component.
|
441
|
+
* @param {Option[]} options - Array of options to display in the dropdown.
|
442
|
+
* @param {boolean} multi - Enables multi-selection mode.
|
443
|
+
* @param {boolean} disabled - Disables the dropdown input.
|
444
|
+
* @param {keyof Option} sortBy - Key to sort options by (e.g., 'id').
|
445
|
+
* @param {boolean} separator - If true, adds a separator line between options.
|
446
|
+
* @param {boolean} closeOnScroll - Closes the dropdown if the user scrolls the list.
|
447
|
+
* @param {boolean} closeOnSelect - Closes the dropdown on selection in single-select mode.
|
448
|
+
* @param {number} maxSelection - Maximum number of items selectable in multi-select mode.
|
449
|
+
*/
|
450
|
+
var InputList = function InputList(_a) {
|
451
|
+
var name = _a.name,
|
452
|
+
_b = _a.placeholder,
|
453
|
+
placeholder = _b === void 0 ? "Choose value/s" : _b,
|
454
|
+
style = _a.style,
|
455
|
+
options = _a.options,
|
456
|
+
_c = _a.multi,
|
457
|
+
multi = _c === void 0 ? false : _c,
|
458
|
+
_d = _a.disabled,
|
459
|
+
disabled = _d === void 0 ? false : _d,
|
460
|
+
sortBy = _a.sortBy,
|
461
|
+
_e = _a.separator,
|
462
|
+
separator = _e === void 0 ? false : _e,
|
463
|
+
_f = _a.closeOnScroll,
|
464
|
+
closeOnScroll = _f === void 0 ? false : _f,
|
465
|
+
_g = _a.closeOnSelect,
|
466
|
+
closeOnSelect = _g === void 0 ? true : _g,
|
467
|
+
maxSelection = _a.maxSelection;
|
468
|
+
var _h = useFormContext(),
|
469
|
+
formValues = _h.formValues,
|
470
|
+
setFormValue = _h.setFormValue;
|
471
|
+
var _j = useState(false),
|
472
|
+
isDropdownVisible = _j[0],
|
473
|
+
setIsDropdownVisible = _j[1];
|
474
|
+
var selectedOptions = formValues[name] || (multi ? [] : null);
|
475
|
+
var sortedOptions = sortBy ? __spreadArray([], options, true).sort(function (a, b) {
|
476
|
+
return a[sortBy] > b[sortBy] ? 1 : -1;
|
477
|
+
}) : options;
|
478
|
+
var theme = useContext(ThemeContext).theme;
|
479
|
+
var colors = theme.colors;
|
480
|
+
/**
|
481
|
+
* Handles selection of an option. Adds or removes the option from selectedOptions based on
|
482
|
+
* multi-selection and maxSelection criteria.
|
483
|
+
* @param {Option} option - The selected option object.
|
484
|
+
*/
|
485
|
+
var handleSelectOption = function handleSelectOption(option) {
|
486
|
+
if (multi) {
|
487
|
+
var alreadySelected = selectedOptions.some(function (opt) {
|
488
|
+
return opt.id === option.id;
|
489
|
+
});
|
490
|
+
// Add or remove item from selected options
|
491
|
+
var updatedSelections = alreadySelected ? selectedOptions.filter(function (opt) {
|
492
|
+
return opt.id !== option.id;
|
493
|
+
}) : __spreadArray(__spreadArray([], selectedOptions, true), [option], false);
|
494
|
+
// Close dropdown if max selection is reached after selecting
|
495
|
+
if (!alreadySelected && maxSelection && updatedSelections.length >= maxSelection) {
|
496
|
+
setIsDropdownVisible(false);
|
497
|
+
}
|
498
|
+
// Update form value
|
499
|
+
setFormValue(name, updatedSelections);
|
500
|
+
} else {
|
501
|
+
setFormValue(name, option);
|
502
|
+
if (closeOnSelect) setIsDropdownVisible(false);
|
503
|
+
}
|
504
|
+
};
|
505
|
+
/**
|
506
|
+
* Renders selected options as a comma-separated string or the placeholder if none selected.
|
507
|
+
* @returns {string} - The display text for selected options or placeholder.
|
508
|
+
*/
|
509
|
+
var renderSelectedText = function renderSelectedText() {
|
510
|
+
if (multi) return selectedOptions.map(function (opt) {
|
511
|
+
return opt.label;
|
512
|
+
}).join(', ') || placeholder;
|
513
|
+
return (selectedOptions === null || selectedOptions === void 0 ? void 0 : selectedOptions.label) || placeholder;
|
514
|
+
};
|
515
|
+
/**
|
516
|
+
* Toggles dropdown visibility. Disables toggle if the component is disabled.
|
517
|
+
*/
|
518
|
+
var toggleDropdown = function toggleDropdown() {
|
519
|
+
if (!disabled) {
|
520
|
+
setIsDropdownVisible(!isDropdownVisible);
|
521
|
+
if (!isDropdownVisible) Keyboard.dismiss();
|
522
|
+
}
|
523
|
+
};
|
524
|
+
/**
|
525
|
+
* Closes the dropdown when pressing outside.
|
526
|
+
*/
|
527
|
+
var handleCloseDropdown = useCallback(function () {
|
528
|
+
if (isDropdownVisible) setIsDropdownVisible(false);
|
529
|
+
}, [isDropdownVisible]);
|
530
|
+
// Conditionally render item as disabled if max selection reached and item is unselected
|
531
|
+
var isItemDisabled = function isItemDisabled(option) {
|
532
|
+
return multi && maxSelection && selectedOptions.length >= maxSelection && !selectedOptions.some(function (opt) {
|
533
|
+
return opt.id === option.id;
|
534
|
+
});
|
535
|
+
};
|
536
|
+
return /*#__PURE__*/React.createElement(View, {
|
537
|
+
style: [styles$2.container, style]
|
538
|
+
}, /*#__PURE__*/React.createElement(TouchableOpacity, {
|
539
|
+
style: styles$2.inputContainer,
|
540
|
+
onPress: toggleDropdown,
|
541
|
+
disabled: disabled
|
542
|
+
}, /*#__PURE__*/React.createElement(Text$1, {
|
543
|
+
style: {
|
544
|
+
color: colors.text.hex
|
545
|
+
}
|
546
|
+
}, renderSelectedText())), /*#__PURE__*/React.createElement(Modal, {
|
547
|
+
visible: isDropdownVisible,
|
548
|
+
transparent: true,
|
549
|
+
animationType: "fade"
|
550
|
+
}, /*#__PURE__*/React.createElement(Pressable, {
|
551
|
+
style: styles$2.overlay,
|
552
|
+
onPress: handleCloseDropdown
|
553
|
+
}), /*#__PURE__*/React.createElement(View, {
|
554
|
+
style: [styles$2.dropdownContainer, {
|
555
|
+
backgroundColor: colors.body.hex
|
556
|
+
}]
|
557
|
+
}, /*#__PURE__*/React.createElement(FlatList, {
|
558
|
+
data: sortedOptions,
|
559
|
+
keyExtractor: function keyExtractor(item) {
|
560
|
+
return item.id.toString();
|
561
|
+
},
|
562
|
+
renderItem: function renderItem(_a) {
|
563
|
+
var item = _a.item;
|
564
|
+
var isSelected = selectedOptions.some(function (opt) {
|
565
|
+
return opt.id === item.id;
|
566
|
+
});
|
567
|
+
var isDisabled = isItemDisabled(item);
|
568
|
+
return /*#__PURE__*/React.createElement(TouchableOpacity, {
|
569
|
+
onPress: function onPress() {
|
570
|
+
return handleSelectOption(item);
|
571
|
+
},
|
572
|
+
style: [styles$2.optionItem, isSelected ? {
|
573
|
+
backgroundColor: colors.primary.hex
|
574
|
+
} : {}, isDisabled ? styles$2.disabledItem : {}],
|
575
|
+
disabled: !!isDisabled
|
576
|
+
}, /*#__PURE__*/React.createElement(Text$1, {
|
577
|
+
style: [{
|
578
|
+
color: colors.primary.hex
|
579
|
+
}, isDisabled ? styles$2.disabledText : {}]
|
580
|
+
}, item.label));
|
581
|
+
},
|
582
|
+
ItemSeparatorComponent: function ItemSeparatorComponent() {
|
583
|
+
return separator ? /*#__PURE__*/React.createElement(View, {
|
584
|
+
style: styles$2.separator
|
585
|
+
}) : null;
|
586
|
+
},
|
587
|
+
scrollEnabled: !closeOnScroll
|
588
|
+
}))));
|
589
|
+
};
|
590
|
+
var styles$2 = StyleSheet.create({
|
591
|
+
container: {
|
592
|
+
padding: 8
|
593
|
+
},
|
594
|
+
inputContainer: {
|
595
|
+
padding: 12,
|
596
|
+
borderWidth: 1,
|
597
|
+
borderColor: '#ccc',
|
598
|
+
borderRadius: 5
|
599
|
+
},
|
600
|
+
dropdownContainer: {
|
601
|
+
position: 'absolute',
|
602
|
+
top: '30%',
|
603
|
+
// Center the dropdown vertically
|
604
|
+
alignSelf: 'center',
|
605
|
+
width: '90%',
|
606
|
+
backgroundColor: '#fff',
|
607
|
+
borderRadius: 8,
|
608
|
+
elevation: 5,
|
609
|
+
paddingVertical: 10
|
610
|
+
},
|
611
|
+
optionItem: {
|
612
|
+
padding: 12
|
613
|
+
},
|
614
|
+
disabledItem: {
|
615
|
+
backgroundColor: '#f0f0f0'
|
616
|
+
},
|
617
|
+
disabledText: {
|
618
|
+
color: '#999'
|
619
|
+
},
|
620
|
+
separator: {
|
621
|
+
height: 1,
|
622
|
+
backgroundColor: '#ddd',
|
623
|
+
marginHorizontal: 8
|
624
|
+
},
|
625
|
+
overlay: {
|
626
|
+
flex: 1,
|
627
|
+
backgroundColor: 'rgba(0,0,0,0.3)'
|
628
|
+
}
|
629
|
+
});
|
630
|
+
|
425
631
|
// src/components/Button.tsx
|
426
632
|
/**
|
427
633
|
* Determines the styles based on the button type and whether it is disabled.
|
@@ -600,5 +806,5 @@ var styles = StyleSheet.create({
|
|
600
806
|
}
|
601
807
|
});
|
602
808
|
|
603
|
-
export { Button, Card, ErrorList, Form, Input, Label, Text, TextArea, useFormContext };
|
809
|
+
export { Button, Card, ErrorList, Form, Input, InputList, Label, Text, TextArea, useFormContext };
|
604
810
|
//# sourceMappingURL=index.esm.js.map
|