aport-tools 4.1.1 → 4.1.21

Sign up to get free protection for your applications and to get access to all the features.
@@ -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