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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! aport-tools v4.2.0 | ISC */
1
+ /*! aport-tools v4.2.2 | ISC */
2
2
  'use strict';
3
3
 
4
4
  var React = require('react');
@@ -83,6 +83,16 @@ function __generator(thisArg, body) {
83
83
  }
84
84
  }
85
85
 
86
+ function __spreadArray(to, from, pack) {
87
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
88
+ if (ar || !(i in from)) {
89
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
90
+ ar[i] = from[i];
91
+ }
92
+ }
93
+ return to.concat(ar || Array.prototype.slice.call(from));
94
+ }
95
+
86
96
  typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
87
97
  var e = new Error(message);
88
98
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
@@ -222,23 +232,23 @@ var ErrorList = function ErrorList(_a) {
222
232
  var theme = React.useContext(aportThemes.ThemeContext).theme;
223
233
  var colors = theme.colors;
224
234
  return /*#__PURE__*/React.createElement(reactNative.View, {
225
- style: styles$5.container
235
+ style: styles$6.container
226
236
  }, errors.map(function (error, index) {
227
237
  return /*#__PURE__*/React.createElement(reactNative.View, {
228
238
  key: index,
229
- style: styles$5.errorItem
239
+ style: styles$6.errorItem
230
240
  }, /*#__PURE__*/React.createElement(Text, {
231
- style: [styles$5.bullet, {
241
+ style: [styles$6.bullet, {
232
242
  color: colors.error.hex
233
243
  }]
234
244
  }, "\u2022"), /*#__PURE__*/React.createElement(Text, {
235
- style: [styles$5.errorText, {
245
+ style: [styles$6.errorText, {
236
246
  color: colors.error.hex
237
247
  }]
238
248
  }, error));
239
249
  }));
240
250
  };
241
- var styles$5 = reactNative.StyleSheet.create({
251
+ var styles$6 = reactNative.StyleSheet.create({
242
252
  container: {
243
253
  marginTop: 4
244
254
  },
@@ -316,13 +326,13 @@ var Input = function Input(_a) {
316
326
  setFormValue(name, formattedText);
317
327
  };
318
328
  return /*#__PURE__*/React.createElement(reactNative.View, {
319
- style: styles$4.container
329
+ style: styles$5.container
320
330
  }, /*#__PURE__*/React.createElement(Text, {
321
- style: [styles$4.label, {
331
+ style: [styles$5.label, {
322
332
  color: colors.text.hex
323
333
  }]
324
334
  }, label), /*#__PURE__*/React.createElement(reactNative.TextInput, __assign({
325
- style: [styles$4.input, {
335
+ style: [styles$5.input, {
326
336
  backgroundColor: colors.body.hex,
327
337
  borderColor: formErrors[name] ? colors.error.hex : "#CCC",
328
338
  color: colors.text.hex
@@ -335,7 +345,7 @@ var Input = function Input(_a) {
335
345
  errors: formErrors[name]
336
346
  })));
337
347
  };
338
- var styles$4 = reactNative.StyleSheet.create({
348
+ var styles$5 = reactNative.StyleSheet.create({
339
349
  container: {
340
350
  marginBottom: 16
341
351
  },
@@ -366,11 +376,11 @@ var TextArea = function TextArea(_a) {
366
376
  setFormValue(name, text);
367
377
  };
368
378
  return /*#__PURE__*/React.createElement(reactNative.View, {
369
- style: styles$3.container
379
+ style: styles$4.container
370
380
  }, /*#__PURE__*/React.createElement(Text, {
371
- style: styles$3.label
381
+ style: styles$4.label
372
382
  }, label), /*#__PURE__*/React.createElement(reactNative.TextInput, __assign({
373
- style: [styles$3.textArea, style],
383
+ style: [styles$4.textArea, style],
374
384
  value: formValues[name] || '',
375
385
  onChangeText: handleChange,
376
386
  placeholder: label,
@@ -383,7 +393,7 @@ var TextArea = function TextArea(_a) {
383
393
  errors: formErrors[name]
384
394
  })));
385
395
  };
386
- var styles$3 = reactNative.StyleSheet.create({
396
+ var styles$4 = reactNative.StyleSheet.create({
387
397
  container: {
388
398
  marginBottom: 16
389
399
  },
@@ -412,18 +422,214 @@ var Label = function Label(_a) {
412
422
  var theme = React.useContext(aportThemes.ThemeContext).theme;
413
423
  var colors = theme.colors;
414
424
  return /*#__PURE__*/React.createElement(Text, {
415
- style: [styles$2.label, style, {
425
+ style: [styles$3.label, style, {
416
426
  color: colors.text.hex
417
427
  }]
418
428
  }, text);
419
429
  };
420
- var styles$2 = reactNative.StyleSheet.create({
430
+ var styles$3 = reactNative.StyleSheet.create({
421
431
  label: {
422
432
  marginBottom: 4,
423
433
  fontWeight: '500'
424
434
  }
425
435
  });
426
436
 
437
+ /**
438
+ * InputList component - A custom dropdown list component for React Native with multi-selection support,
439
+ * customizable styling, sorting, and configurable close behavior on selection or scrolling.
440
+ *
441
+ * @param {string} placeholder - Placeholder text for the input.
442
+ * @param {object} style - Custom styles for the component.
443
+ * @param {Option[]} options - Array of options to display in the dropdown.
444
+ * @param {boolean} multi - Enables multi-selection mode.
445
+ * @param {boolean} disabled - Disables the dropdown input.
446
+ * @param {keyof Option} sortBy - Key to sort options by (e.g., 'id').
447
+ * @param {boolean} separator - If true, adds a separator line between options.
448
+ * @param {boolean} closeOnScroll - Closes the dropdown if the user scrolls the list.
449
+ * @param {boolean} closeOnSelect - Closes the dropdown on selection in single-select mode.
450
+ * @param {number} maxSelection - Maximum number of items selectable in multi-select mode.
451
+ */
452
+ var InputList = function InputList(_a) {
453
+ var name = _a.name,
454
+ _b = _a.placeholder,
455
+ placeholder = _b === void 0 ? "Choose value/s" : _b,
456
+ style = _a.style,
457
+ options = _a.options,
458
+ _c = _a.multi,
459
+ multi = _c === void 0 ? false : _c,
460
+ _d = _a.disabled,
461
+ disabled = _d === void 0 ? false : _d,
462
+ sortBy = _a.sortBy,
463
+ _e = _a.separator,
464
+ separator = _e === void 0 ? false : _e,
465
+ _f = _a.closeOnScroll,
466
+ closeOnScroll = _f === void 0 ? false : _f,
467
+ _g = _a.closeOnSelect,
468
+ closeOnSelect = _g === void 0 ? true : _g,
469
+ maxSelection = _a.maxSelection;
470
+ var _h = useFormContext(),
471
+ formValues = _h.formValues,
472
+ setFormValue = _h.setFormValue;
473
+ var _j = React.useState(false),
474
+ isDropdownVisible = _j[0],
475
+ setIsDropdownVisible = _j[1];
476
+ var selectedOptions = formValues[name] || (multi ? [] : null);
477
+ var sortedOptions = sortBy ? __spreadArray([], options, true).sort(function (a, b) {
478
+ return a[sortBy] > b[sortBy] ? 1 : -1;
479
+ }) : options;
480
+ var theme = React.useContext(aportThemes.ThemeContext).theme;
481
+ var colors = theme.colors;
482
+ /**
483
+ * Handles selection of an option. Adds or removes the option from selectedOptions based on
484
+ * multi-selection and maxSelection criteria.
485
+ * @param {Option} option - The selected option object.
486
+ */
487
+ var handleSelectOption = function handleSelectOption(option) {
488
+ if (multi) {
489
+ var alreadySelected = selectedOptions.some(function (opt) {
490
+ return opt.id === option.id;
491
+ });
492
+ // Add or remove item from selected options
493
+ var updatedSelections = alreadySelected ? selectedOptions.filter(function (opt) {
494
+ return opt.id !== option.id;
495
+ }) : __spreadArray(__spreadArray([], selectedOptions, true), [option], false);
496
+ // Close dropdown if max selection is reached after selecting
497
+ if (!alreadySelected && maxSelection && updatedSelections.length >= maxSelection) {
498
+ setIsDropdownVisible(false);
499
+ }
500
+ // Update form value
501
+ setFormValue(name, updatedSelections);
502
+ } else {
503
+ setFormValue(name, option);
504
+ if (closeOnSelect) setIsDropdownVisible(false);
505
+ }
506
+ };
507
+ /**
508
+ * Renders selected options as a comma-separated string or the placeholder if none selected.
509
+ * @returns {string} - The display text for selected options or placeholder.
510
+ */
511
+ var renderSelectedText = function renderSelectedText() {
512
+ if (multi) return selectedOptions.map(function (opt) {
513
+ return opt.label;
514
+ }).join(', ') || placeholder;
515
+ return (selectedOptions === null || selectedOptions === void 0 ? void 0 : selectedOptions.label) || placeholder;
516
+ };
517
+ /**
518
+ * Toggles dropdown visibility. Disables toggle if the component is disabled.
519
+ */
520
+ var toggleDropdown = function toggleDropdown() {
521
+ if (!disabled) {
522
+ setIsDropdownVisible(!isDropdownVisible);
523
+ if (!isDropdownVisible) reactNative.Keyboard.dismiss();
524
+ }
525
+ };
526
+ /**
527
+ * Closes the dropdown when pressing outside.
528
+ */
529
+ var handleCloseDropdown = React.useCallback(function () {
530
+ if (isDropdownVisible) setIsDropdownVisible(false);
531
+ }, [isDropdownVisible]);
532
+ // Conditionally render item as disabled if max selection reached and item is unselected
533
+ var isItemDisabled = function isItemDisabled(option) {
534
+ return multi && maxSelection && selectedOptions.length >= maxSelection && !selectedOptions.some(function (opt) {
535
+ return opt.id === option.id;
536
+ });
537
+ };
538
+ return /*#__PURE__*/React.createElement(reactNative.View, {
539
+ style: [styles$2.container, style]
540
+ }, /*#__PURE__*/React.createElement(reactNative.TouchableOpacity, {
541
+ style: styles$2.inputContainer,
542
+ onPress: toggleDropdown,
543
+ disabled: disabled
544
+ }, /*#__PURE__*/React.createElement(reactNative.Text, {
545
+ style: {
546
+ color: colors.text.hex
547
+ }
548
+ }, renderSelectedText())), /*#__PURE__*/React.createElement(reactNative.Modal, {
549
+ visible: isDropdownVisible,
550
+ transparent: true,
551
+ animationType: "fade"
552
+ }, /*#__PURE__*/React.createElement(reactNative.Pressable, {
553
+ style: styles$2.overlay,
554
+ onPress: handleCloseDropdown
555
+ }), /*#__PURE__*/React.createElement(reactNative.View, {
556
+ style: [styles$2.dropdownContainer, {
557
+ backgroundColor: colors.body.hex
558
+ }]
559
+ }, /*#__PURE__*/React.createElement(reactNative.FlatList, {
560
+ data: sortedOptions,
561
+ keyExtractor: function keyExtractor(item) {
562
+ return item.id.toString();
563
+ },
564
+ renderItem: function renderItem(_a) {
565
+ var item = _a.item;
566
+ var isSelected = selectedOptions.some(function (opt) {
567
+ return opt.id === item.id;
568
+ });
569
+ var isDisabled = isItemDisabled(item);
570
+ return /*#__PURE__*/React.createElement(reactNative.TouchableOpacity, {
571
+ onPress: function onPress() {
572
+ return handleSelectOption(item);
573
+ },
574
+ style: [styles$2.optionItem, isSelected ? {
575
+ backgroundColor: colors.primary.hex
576
+ } : {}, isDisabled ? styles$2.disabledItem : {}],
577
+ disabled: !!isDisabled
578
+ }, /*#__PURE__*/React.createElement(reactNative.Text, {
579
+ style: [{
580
+ color: colors.primary.hex
581
+ }, isDisabled ? styles$2.disabledText : {}]
582
+ }, item.label));
583
+ },
584
+ ItemSeparatorComponent: function ItemSeparatorComponent() {
585
+ return separator ? /*#__PURE__*/React.createElement(reactNative.View, {
586
+ style: styles$2.separator
587
+ }) : null;
588
+ },
589
+ scrollEnabled: !closeOnScroll
590
+ }))));
591
+ };
592
+ var styles$2 = reactNative.StyleSheet.create({
593
+ container: {
594
+ padding: 8
595
+ },
596
+ inputContainer: {
597
+ padding: 12,
598
+ borderWidth: 1,
599
+ borderColor: '#ccc',
600
+ borderRadius: 5
601
+ },
602
+ dropdownContainer: {
603
+ position: 'absolute',
604
+ top: '30%',
605
+ // Center the dropdown vertically
606
+ alignSelf: 'center',
607
+ width: '90%',
608
+ backgroundColor: '#fff',
609
+ borderRadius: 8,
610
+ elevation: 5,
611
+ paddingVertical: 10
612
+ },
613
+ optionItem: {
614
+ padding: 12
615
+ },
616
+ disabledItem: {
617
+ backgroundColor: '#f0f0f0'
618
+ },
619
+ disabledText: {
620
+ color: '#999'
621
+ },
622
+ separator: {
623
+ height: 1,
624
+ backgroundColor: '#ddd',
625
+ marginHorizontal: 8
626
+ },
627
+ overlay: {
628
+ flex: 1,
629
+ backgroundColor: 'rgba(0,0,0,0.3)'
630
+ }
631
+ });
632
+
427
633
  // src/components/Button.tsx
428
634
  /**
429
635
  * Determines the styles based on the button type and whether it is disabled.
@@ -607,6 +813,7 @@ exports.Card = Card;
607
813
  exports.ErrorList = ErrorList;
608
814
  exports.Form = Form;
609
815
  exports.Input = Input;
816
+ exports.InputList = InputList;
610
817
  exports.Label = Label;
611
818
  exports.Text = Text;
612
819
  exports.TextArea = TextArea;