aport-tools 4.1.1 → 4.1.21

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.
@@ -31,6 +31,10 @@ interface ButtonProps {
31
31
  * Specifies the button type for styling. Can be 'submit', 'button', or 'cancel'.
32
32
  */
33
33
  type?: 'submit' | 'button' | 'cancel';
34
+ /**
35
+ * If true, a loading spinner is shown and the button is disabled.
36
+ */
37
+ loading?: boolean;
34
38
  }
35
39
  /**
36
40
  * Button component that adapts its styles based on the current theme.
@@ -38,7 +38,7 @@ interface CustomTextProps extends TextProps {
38
38
  /**
39
39
  * Additional styles to apply to the Text component.
40
40
  */
41
- style?: TextStyle;
41
+ style?: TextStyle | TextStyle[];
42
42
  }
43
43
  /**
44
44
  * A dynamic Text component that supports HTML-like formatting.
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface ErrorListProps {
3
+ errors: string[];
4
+ }
5
+ declare const ErrorList: React.FC<ErrorListProps>;
6
+ export default ErrorList;
@@ -0,0 +1 @@
1
+ export { Form, useFormContext } from './FormContext';
@@ -0,0 +1,15 @@
1
+ import React, { ReactNode } from 'react';
2
+ interface FormContextProps {
3
+ formValues: Record<string, any>;
4
+ setFormValue: (name: string, value: any) => void;
5
+ errors: Record<string, string[]>;
6
+ setErrors: (errors: Record<string, string[]>) => void;
7
+ handleSubmit: () => void;
8
+ }
9
+ export declare const useFormContext: () => FormContextProps;
10
+ interface FormProps {
11
+ children: ReactNode;
12
+ onSubmit: (values: Record<string, any>) => Promise<Record<string, string[]>>;
13
+ }
14
+ export declare const Form: React.FC<FormProps>;
15
+ export {};
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { TextInputProps } from 'react-native';
3
+ interface InputProps extends TextInputProps {
4
+ name: string;
5
+ label: string;
6
+ }
7
+ export declare const Input: React.FC<InputProps>;
8
+ export {};
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface LabelProps {
3
+ text: string;
4
+ style?: any;
5
+ }
6
+ declare const Label: React.FC<LabelProps>;
7
+ export default Label;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { TextInputProps } from 'react-native';
3
+ interface TextAreaProps extends TextInputProps {
4
+ name: string;
5
+ label: string;
6
+ errors?: string[];
7
+ }
8
+ declare const TextArea: React.FC<TextAreaProps>;
9
+ export default TextArea;
@@ -0,0 +1,5 @@
1
+ export { Input } from './Input';
2
+ export { Form, useFormContext } from './FormContext';
3
+ export { default as TextArea } from './TextArea';
4
+ export { default as Label } from './Label';
5
+ export { default as ErrorList } from './ErrorList';
package/dist/index.d.ts CHANGED
@@ -2,3 +2,4 @@ export * from './theme';
2
2
  export * from './buttons';
3
3
  export * from './cards';
4
4
  export * from './fonts';
5
+ export * from './forms';
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
- /*! aport-tools v4.1.1 | ISC */
1
+ /*! aport-tools v4.1.21 | ISC */
2
2
  import React, { createContext, useState, useEffect, useContext, useMemo } from 'react';
3
- import { Appearance, StyleSheet, View, Text as Text$1, Switch, TouchableOpacity, Platform } from 'react-native';
3
+ import { Appearance, StyleSheet, View, Text as Text$1, Switch, TouchableOpacity, ActivityIndicator, Platform, TextInput } from 'react-native';
4
4
  import { useAsyncStorage } from '@react-native-async-storage/async-storage';
5
5
 
6
6
  /******************************************************************************
@@ -20,6 +20,29 @@ PERFORMANCE OF THIS SOFTWARE.
20
20
  /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
21
21
 
22
22
 
23
+ var __assign = function() {
24
+ __assign = Object.assign || function __assign(t) {
25
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
26
+ s = arguments[i];
27
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
28
+ }
29
+ return t;
30
+ };
31
+ return __assign.apply(this, arguments);
32
+ };
33
+
34
+ function __rest(s, e) {
35
+ var t = {};
36
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
37
+ t[p] = s[p];
38
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
39
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
40
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
41
+ t[p[i]] = s[p[i]];
42
+ }
43
+ return t;
44
+ }
45
+
23
46
  function __awaiter(thisArg, _arguments, P, generator) {
24
47
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
25
48
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -313,9 +336,9 @@ var ThemeToggle = function ThemeToggle() {
313
336
  toggleTheme = _a.toggleTheme;
314
337
  var isDarkMode = theme.colors === darkTheme;
315
338
  return /*#__PURE__*/React.createElement(View, {
316
- style: styles$2.container
339
+ style: styles$6.container
317
340
  }, /*#__PURE__*/React.createElement(Text$1, {
318
- style: [styles$2.text, {
341
+ style: [styles$6.text, {
319
342
  color: theme.colors.text.hex
320
343
  }]
321
344
  }, "Dark Mode"), /*#__PURE__*/React.createElement(Switch, {
@@ -328,7 +351,7 @@ var ThemeToggle = function ThemeToggle() {
328
351
  thumbColor: isDarkMode ? darkTheme.secondary.hex : lightTheme.primary.hex
329
352
  }));
330
353
  };
331
- var styles$2 = StyleSheet.create({
354
+ var styles$6 = StyleSheet.create({
332
355
  container: {
333
356
  marginTop: 20,
334
357
  flexDirection: 'row',
@@ -397,16 +420,18 @@ var Button = function Button(_a) {
397
420
  borderRadius = _e === void 0 ? 30 : _e,
398
421
  _f = _a.isFullWidth,
399
422
  isFullWidth = _f === void 0 ? false : _f,
423
+ _g = _a.loading,
424
+ loading = _g === void 0 ? false : _g,
400
425
  onPress = _a.onPress;
401
426
  var theme = useContext(ThemeContext).theme;
402
427
  var colors = theme.colors;
403
428
  var computedStyles = useMemo(function () {
404
- return StyleSheet.flatten([styles$1.button, typeStyles(type, disabled, colors), rounded && {
429
+ return StyleSheet.flatten([styles$5.button, typeStyles(type, disabled, colors), rounded && {
405
430
  borderRadius: borderRadius
406
431
  }, isFullWidth && {
407
432
  width: '100%'
408
- }, disabled && styles$1.disabled]);
409
- }, [type, disabled, rounded, borderRadius, isFullWidth, colors]);
433
+ }, (disabled || loading) && styles$5.disabled]);
434
+ }, [type, disabled, loading, rounded, borderRadius, isFullWidth, colors]);
410
435
  var textColor = useMemo(function () {
411
436
  return {
412
437
  color: colors.textButton.hex
@@ -414,14 +439,20 @@ var Button = function Button(_a) {
414
439
  }, [type, colors]);
415
440
  return /*#__PURE__*/React.createElement(TouchableOpacity, {
416
441
  style: computedStyles,
417
- disabled: disabled,
442
+ disabled: disabled || loading,
418
443
  onPress: onPress,
419
444
  activeOpacity: 0.7
420
- }, /*#__PURE__*/React.createElement(Text$1, {
445
+ }, loading ? (
446
+ /*#__PURE__*/
447
+ // Show loading spinner if loading
448
+ React.createElement(ActivityIndicator, {
449
+ size: "small",
450
+ color: colors.textButton.hex
451
+ })) : (/*#__PURE__*/React.createElement(Text$1, {
421
452
  style: textColor
422
- }, Array.isArray(children) ? children.join('').toUpperCase() : children === null || children === void 0 ? void 0 : children.toUpperCase()));
453
+ }, Array.isArray(children) ? children.join('').toUpperCase() : children === null || children === void 0 ? void 0 : children.toUpperCase())));
423
454
  };
424
- var styles$1 = StyleSheet.create({
455
+ var styles$5 = StyleSheet.create({
425
456
  button: {
426
457
  justifyContent: 'center',
427
458
  alignItems: 'center',
@@ -477,7 +508,7 @@ var Card = function Card(_a) {
477
508
  elevation: elevation // Only applies to Android
478
509
  }
479
510
  });
480
- var cardStyles = [styles.container, {
511
+ var cardStyles = [styles$4.container, {
481
512
  borderRadius: borderRadius,
482
513
  backgroundColor: colors.body.hex
483
514
  }, defaultShadow,
@@ -492,7 +523,7 @@ var Card = function Card(_a) {
492
523
  style: cardStyles
493
524
  }, children));
494
525
  };
495
- var styles = StyleSheet.create({
526
+ var styles$4 = StyleSheet.create({
496
527
  container: {
497
528
  padding: 16,
498
529
  borderRadius: 12
@@ -564,5 +595,216 @@ StyleSheet.create({
564
595
  // Define any default styles if needed
565
596
  });
566
597
 
567
- export { Button, Card, Text, ThemeContext, ThemeProvider, ThemeToggle };
598
+ // src/forms/FormContext.tsx
599
+ var FormContext = /*#__PURE__*/createContext(undefined);
600
+ var useFormContext = function useFormContext() {
601
+ var context = useContext(FormContext);
602
+ if (!context) {
603
+ throw new Error("useFormContext must be used within a Form");
604
+ }
605
+ return context;
606
+ };
607
+ var Form = function Form(_a) {
608
+ var children = _a.children,
609
+ onSubmit = _a.onSubmit;
610
+ var _b = useState({}),
611
+ formValues = _b[0],
612
+ setFormValues = _b[1];
613
+ var _c = useState({}),
614
+ errors = _c[0],
615
+ setErrors = _c[1];
616
+ var setFormValue = function setFormValue(name, value) {
617
+ setFormValues(function (prev) {
618
+ var _a;
619
+ return __assign(__assign({}, prev), (_a = {}, _a[name] = value, _a));
620
+ });
621
+ };
622
+ var handleSubmit = function handleSubmit() {
623
+ return __awaiter(void 0, void 0, void 0, function () {
624
+ var validationErrors;
625
+ return __generator(this, function (_a) {
626
+ switch (_a.label) {
627
+ case 0:
628
+ return [4 /*yield*/, onSubmit(formValues)];
629
+ case 1:
630
+ validationErrors = _a.sent();
631
+ setErrors(validationErrors);
632
+ return [2 /*return*/];
633
+ }
634
+ });
635
+ });
636
+ };
637
+ return /*#__PURE__*/React.createElement(FormContext.Provider, {
638
+ value: {
639
+ formValues: formValues,
640
+ setFormValue: setFormValue,
641
+ errors: errors,
642
+ setErrors: setErrors,
643
+ handleSubmit: handleSubmit
644
+ }
645
+ }, children);
646
+ };
647
+
648
+ // src/forms/ErrorList.tsx
649
+ var ErrorList = function ErrorList(_a) {
650
+ var errors = _a.errors;
651
+ return /*#__PURE__*/React.createElement(View, {
652
+ style: styles$3.container
653
+ }, errors.map(function (error, index) {
654
+ return /*#__PURE__*/React.createElement(View, {
655
+ key: index,
656
+ style: styles$3.errorItem
657
+ }, /*#__PURE__*/React.createElement(Text, {
658
+ style: styles$3.bullet
659
+ }, "\u2022"), /*#__PURE__*/React.createElement(Text, {
660
+ style: styles$3.errorText
661
+ }, error));
662
+ }));
663
+ };
664
+ var styles$3 = StyleSheet.create({
665
+ container: {
666
+ marginTop: 4
667
+ },
668
+ errorItem: {
669
+ flexDirection: 'row',
670
+ alignItems: 'flex-start',
671
+ marginBottom: 2
672
+ },
673
+ bullet: {
674
+ marginRight: 4,
675
+ color: '#FF5252',
676
+ // Should use 'error' color from theme
677
+ fontSize: 12
678
+ },
679
+ errorText: {
680
+ flex: 1,
681
+ color: '#FF5252',
682
+ // Should use 'error' color from theme
683
+ fontSize: 12
684
+ }
685
+ });
686
+
687
+ // src/forms/Input.tsx
688
+ var Input = function Input(_a) {
689
+ var name = _a.name,
690
+ label = _a.label,
691
+ style = _a.style,
692
+ rest = __rest(_a, ["name", "label", "style"]);
693
+ var _b = useFormContext(),
694
+ formValues = _b.formValues,
695
+ setFormValue = _b.setFormValue,
696
+ formErrors = _b.errors;
697
+ var theme = useContext(ThemeContext).theme;
698
+ var colors = theme.colors;
699
+ var handleChange = function handleChange(text) {
700
+ setFormValue(name, text);
701
+ };
702
+ return /*#__PURE__*/React.createElement(View, {
703
+ style: styles$2.container
704
+ }, /*#__PURE__*/React.createElement(Text, {
705
+ style: [styles$2.label, {
706
+ color: colors.text.hex
707
+ }]
708
+ }, label), /*#__PURE__*/React.createElement(TextInput, __assign({
709
+ style: [styles$2.input, {
710
+ backgroundColor: colors.body.hex,
711
+ borderColor: formErrors[name] ? colors.error.hex : '#CCC',
712
+ color: colors.text.hex
713
+ }, style],
714
+ value: formValues[name] || '',
715
+ onChangeText: handleChange,
716
+ placeholder: label,
717
+ placeholderTextColor: colors.text.hex
718
+ }, rest)), formErrors[name] && formErrors[name].length > 0 && (/*#__PURE__*/React.createElement(ErrorList, {
719
+ errors: formErrors[name]
720
+ })));
721
+ };
722
+ var styles$2 = StyleSheet.create({
723
+ container: {
724
+ marginBottom: 16
725
+ },
726
+ label: {
727
+ marginBottom: 4,
728
+ fontSize: 14
729
+ },
730
+ input: {
731
+ height: 40,
732
+ borderWidth: 1,
733
+ borderRadius: 4,
734
+ paddingHorizontal: 8
735
+ }
736
+ });
737
+
738
+ // src/forms/TextArea.tsx
739
+ var TextArea = function TextArea(_a) {
740
+ var name = _a.name,
741
+ label = _a.label;
742
+ _a.errors;
743
+ var style = _a.style,
744
+ rest = __rest(_a, ["name", "label", "errors", "style"]);
745
+ var _b = useFormContext(),
746
+ formValues = _b.formValues,
747
+ setFormValue = _b.setFormValue,
748
+ formErrors = _b.errors;
749
+ var handleChange = function handleChange(text) {
750
+ setFormValue(name, text);
751
+ };
752
+ return /*#__PURE__*/React.createElement(View, {
753
+ style: styles$1.container
754
+ }, /*#__PURE__*/React.createElement(Text, {
755
+ style: styles$1.label
756
+ }, label), /*#__PURE__*/React.createElement(TextInput, __assign({
757
+ style: [styles$1.textArea, style],
758
+ value: formValues[name] || '',
759
+ onChangeText: handleChange,
760
+ placeholder: label,
761
+ placeholderTextColor: "#888" // Can be themed if needed
762
+ ,
763
+ multiline: true,
764
+ numberOfLines: 4,
765
+ textAlignVertical: "top"
766
+ }, rest)), formErrors[name] && formErrors[name].length > 0 && (/*#__PURE__*/React.createElement(ErrorList, {
767
+ errors: formErrors[name]
768
+ })));
769
+ };
770
+ var styles$1 = StyleSheet.create({
771
+ container: {
772
+ marginBottom: 16
773
+ },
774
+ label: {
775
+ marginBottom: 4,
776
+ color: '#000' // Should be themed
777
+ },
778
+ textArea: {
779
+ height: 100,
780
+ borderColor: '#CCC',
781
+ // Should be themed
782
+ borderWidth: 1,
783
+ borderRadius: 4,
784
+ paddingHorizontal: 8,
785
+ paddingVertical: 8,
786
+ backgroundColor: '#FFFFFF',
787
+ // Should use 'body' color from theme
788
+ color: '#000' // Should use 'text' color from theme
789
+ }
790
+ });
791
+
792
+ // src/forms/Label.tsx
793
+ var Label = function Label(_a) {
794
+ var text = _a.text,
795
+ style = _a.style;
796
+ return /*#__PURE__*/React.createElement(Text, {
797
+ style: [styles.label, style]
798
+ }, text);
799
+ };
800
+ var styles = StyleSheet.create({
801
+ label: {
802
+ marginBottom: 4,
803
+ color: '#000',
804
+ // Should be themed
805
+ fontWeight: '500'
806
+ }
807
+ });
808
+
809
+ export { Button, Card, ErrorList, Form, Input, Label, Text, TextArea, ThemeContext, ThemeProvider, ThemeToggle, useFormContext };
568
810
  //# sourceMappingURL=index.esm.js.map