aport-tools 4.2.0 → 4.2.2
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/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
|