react-native-earl-toastify 1.1.0 → 1.2.0

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/CHANGELOG.md CHANGED
@@ -5,6 +5,71 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.2.0] - 2026-01-31
9
+
10
+ ### Added
11
+
12
+ - 📝 **Input Modal**: New input modal component for collecting user input during sensitive confirmations
13
+ - `InputModal` - Fully customizable input modal with text and OTP/PIN modes
14
+ - `modal.input()` - Generic input modal with full configuration
15
+ - `modal.confirmWithText()` - Confirmation text input (e.g., type "DELETE" to confirm)
16
+ - `modal.otp()` - OTP/verification code input with separate boxes
17
+ - `modal.pin()` - PIN input with masked boxes
18
+
19
+ - 🔢 **OTP/PIN Input Mode**:
20
+ - Separate input boxes for each digit (like bank apps, authenticators)
21
+ - Configurable length (4, 6, 8 digits, etc.)
22
+ - Auto-submit when all boxes are filled
23
+ - Auto-advance to next box on input
24
+ - Backspace navigation between boxes
25
+ - Paste support for codes
26
+
27
+ - 🔒 **Input Restrictions**:
28
+ - `lettersOnly` - Allow only a-zA-Z
29
+ - `numbersOnly` - Allow only 0-9
30
+ - `alphanumericOnly` - Allow only a-zA-Z0-9
31
+ - `disableCopyPaste` - Prevent clipboard access
32
+ - `uppercase` / `lowercase` - Force case transformation
33
+ - `minLength` / `maxLength` - Character length limits
34
+ - `pattern` - Custom regex validation
35
+ - `confirmationText` - Require exact text match
36
+ - `caseSensitive` - Control case-sensitive matching
37
+ - `trimOnSubmit` - Trim whitespace on submit
38
+
39
+ - 🎨 **OTP Box Customization**:
40
+ - `boxWidth`, `boxHeight`, `boxGap`, `boxBorderRadius`
41
+ - `activeBorderColor`, `inactiveBorderColor`, `errorBorderColor`
42
+ - `filledBackgroundColor`, `emptyBackgroundColor`
43
+ - `textColor`, `fontSize`
44
+ - `masked` - Show dots instead of characters
45
+
46
+ - ✨ **Validation**:
47
+ - Real-time validation on change (optional)
48
+ - Custom validator function support
49
+ - Error message display
50
+ - Helper text support
51
+ - Character counter
52
+ - Match indicator for confirmation text
53
+
54
+ - 📦 **New Exports**:
55
+ - `InputModal` component
56
+ - `InputModalConfig`, `InputModalResult`, `InputMode`, `InputRestrictions`, `OtpConfig` types
57
+ - `DEFAULT_OTP_CONFIG`, `DEFAULT_PIN_CONFIG` defaults
58
+ - Input modal styles for customization
59
+
60
+ - ⌨️ **Keyboard Avoidance**: Input modals now automatically move up when the keyboard appears, ensuring input fields and buttons remain visible and accessible
61
+
62
+ - 🔲 **Modal Styling Options**:
63
+ - `rounded` - Option to enable rounded corners (default: `false` for full-width edge-to-edge modal)
64
+ - When `rounded: false`, modal spans full screen width with no margins
65
+ - When `rounded: true`, modal has rounded corners and horizontal margins like the confirmation modal
66
+
67
+ ### Fixed
68
+
69
+ - 🐛 **Toast Variable Arguments**: Fixed a bug where passing string variables as the second argument to toast methods (e.g., `toast.success("Title", messageVariable)`) would only display as a title instead of properly showing both title and description. The `parseArgs` function now correctly handles both literal strings and string variables.
70
+
71
+ ---
72
+
8
73
  ## [1.1.0] - 2026-01-30
9
74
 
10
75
  ### Added
package/README.md CHANGED
@@ -17,13 +17,21 @@ A beautiful, customizable toast notification and confirmation modal library for
17
17
  - 🎯 **Always on Top**: Toasts render above all other content
18
18
  - 📱 **Full-Width Edge Styling**: No rounded corners for top/bottom toasts
19
19
 
20
- ### Confirmation Modal (NEW!)
20
+ ### Confirmation Modal
21
21
 
22
22
  - 🎉 **Promise-based API**: `await modal.confirm()` returns true/false
23
23
  - 🎨 **5 Modal Types**: confirm, warning, danger, info, custom
24
24
  - 🎬 **4 Animation Types**: scale, fade, slide, none
25
25
  - 🔘 **Customizable Buttons**: Text, colors, and styles
26
26
 
27
+ ### Input Modal (NEW!)
28
+
29
+ - 📝 **Text Input Mode**: Standard text input with validation
30
+ - 🔢 **OTP/PIN Mode**: Separate input boxes for verification codes
31
+ - 🔒 **Input Restrictions**: Letters only, numbers only, no copy/paste, and more
32
+ - ✅ **Confirmation Text**: Require user to type exact text (e.g., "DELETE")
33
+ - 🎨 **Fully Customizable**: Box styles, colors, sizes, and validation
34
+
27
35
  ### Common Features
28
36
 
29
37
  - ♿ **WCAG 2.1 AA Accessible**: Proper contrast ratios, screen reader support, 48px touch targets
@@ -91,6 +99,39 @@ A beautiful, customizable toast notification and confirmation modal library for
91
99
  </tr>
92
100
  </table>
93
101
 
102
+ ## ✔️ Input Modal Preview
103
+
104
+ <table>
105
+ <tr>
106
+ <td align="center">
107
+ <b>Confirm</b><br/>
108
+ <img src="https://raw.githubusercontent.com/Swif7ify/react-native-earl-toastify/main/example/11.jpg" width="220"/>
109
+ </td>
110
+ <td align="center">
111
+ <b>Warning</b><br/>
112
+ <img src="https://raw.githubusercontent.com/Swif7ify/react-native-earl-toastify/main/example/12.jpg" width="220"/>
113
+ </td>
114
+ <td align="center">
115
+ <b>Danger</b><br/>
116
+ <img src="https://raw.githubusercontent.com/Swif7ify/react-native-earl-toastify/main/example/13.jpg" width="220"/>
117
+ </td>
118
+ </tr>
119
+ <tr>
120
+ <td align="center">
121
+ <b>Info</b><br/>
122
+ <img src="https://raw.githubusercontent.com/Swif7ify/react-native-earl-toastify/main/example/14.jpg" width="220"/>
123
+ </td>
124
+ <td align="center">
125
+ <b>Custom</b><br/>
126
+ <img src="https://raw.githubusercontent.com/Swif7ify/react-native-earl-toastify/main/example/15.jpg" width="220"/>
127
+ </td>
128
+ <td align="center">
129
+ <b>Custom</b><br/>
130
+ <img src="https://raw.githubusercontent.com/Swif7ify/react-native-earl-toastify/main/example/16.jpg" width="220"/>
131
+ </td>
132
+ </tr>
133
+ </table>
134
+
94
135
  ### 🎥🍞 Toast Demo Video
95
136
 
96
137
  https://github.com/user-attachments/assets/0c96e622-eb7e-4074-ac0a-97a0d04a5d31
@@ -99,6 +140,10 @@ https://github.com/user-attachments/assets/0c96e622-eb7e-4074-ac0a-97a0d04a5d31
99
140
 
100
141
  https://github.com/user-attachments/assets/1b98e721-0aa6-488b-b30b-cc2af8d162cd
101
142
 
143
+ ### 🎥✔️ Input Modal Demo Video
144
+
145
+ https://github.com/user-attachments/assets/1dc2e2bd-8f17-497e-9bb9-82d458f19dc5
146
+
102
147
  ## 📦 Installation
103
148
 
104
149
  ```bash
@@ -406,13 +451,30 @@ interface ToastProviderConfig {
406
451
  ```typescript
407
452
  const toast = useToast();
408
453
 
409
- // Quick methods
410
- toast.success(message: string, config?: Partial<ToastConfig>);
411
- toast.warning(message: string, config?: Partial<ToastConfig>);
412
- toast.error(message: string, config?: Partial<ToastConfig>);
413
- toast.info(message: string, config?: Partial<ToastConfig>);
454
+ // Quick methods - flexible API
455
+ // Option 1: Message only
456
+ toast.success("Operation completed!");
414
457
 
415
- // Custom toast
458
+ // Option 2: Title + Description (both inline or variables)
459
+ toast.success("Success!", "Operation completed successfully");
460
+
461
+ // Option 3: With variables
462
+ const title = "Upload Complete";
463
+ const message = "Your file has been uploaded";
464
+ toast.success(title, message); // Works with variables too!
465
+
466
+ // Option 4: Message + Config
467
+ toast.success("Saved!", { duration: 5000, position: "bottom" });
468
+
469
+ // Option 5: Title + Description + Config
470
+ toast.success("Saved!", "Changes have been applied", { position: "bottom" });
471
+
472
+ // Same API for all types:
473
+ toast.warning(title, message);
474
+ toast.error(title, message);
475
+ toast.info(title, message);
476
+
477
+ // Custom toast with full config
416
478
  toast.show(config: ToastConfig);
417
479
 
418
480
  // Control methods
@@ -712,6 +774,256 @@ await modal.info("Success!", "Your profile has been updated successfully.");
712
774
 
713
775
  ---
714
776
 
777
+ # 📝 Input Modal (NEW!)
778
+
779
+ Input modals allow you to collect user input for sensitive confirmations such as:
780
+
781
+ - **Confirmation text**: E.g., type "DELETE" to confirm account deletion
782
+ - **OTP/Verification codes**: 6-digit codes sent via email or SMS
783
+ - **PIN entry**: 4-digit secure PIN input
784
+
785
+ ## Input Modal Methods
786
+
787
+ ```typescript
788
+ const modal = useModal();
789
+
790
+ // Text input with confirmation text (user must type exact text)
791
+ const result = await modal.confirmWithText(
792
+ "Delete Account",
793
+ "Type DELETE to confirm account deletion",
794
+ "DELETE",
795
+ { caseSensitive: false },
796
+ );
797
+
798
+ if (result.confirmed) {
799
+ // User typed "DELETE" and confirmed
800
+ console.log("User typed:", result.value);
801
+ }
802
+
803
+ // OTP/Verification code input
804
+ const otpResult = await modal.otp(
805
+ "Verify Email",
806
+ "Enter the 6-digit code sent to your email",
807
+ );
808
+
809
+ if (otpResult.confirmed) {
810
+ console.log("Code entered:", otpResult.value); // e.g., "123456"
811
+ }
812
+
813
+ // PIN input (masked by default)
814
+ const pinResult = await modal.pin("Enter PIN", "Enter your 4-digit PIN");
815
+
816
+ // Custom input modal with full configuration
817
+ const customResult = await modal.input({
818
+ title: "Enter Amount",
819
+ message: "How much would you like to transfer?",
820
+ placeholder: "0.00",
821
+ keyboardType: "numeric",
822
+ restrictions: {
823
+ numbersOnly: true,
824
+ maxLength: 10,
825
+ },
826
+ });
827
+ ```
828
+
829
+ ## InputModalConfig
830
+
831
+ | Option | Type | Default | Description |
832
+ | ------------------- | ------------------- | ------------ | --------------------------------------------- |
833
+ | `title` | `string` | **required** | Modal title |
834
+ | `message` | `string` | **required** | Modal message |
835
+ | `inputMode` | `InputMode` | `'text'` | Input type: `text`, `otp`, or `pin` |
836
+ | `placeholder` | `string` | - | Placeholder text for text input |
837
+ | `defaultValue` | `string` | - | Pre-filled value |
838
+ | `restrictions` | `InputRestrictions` | - | Validation and input restrictions |
839
+ | `otpConfig` | `OtpConfig` | - | OTP/PIN box configuration |
840
+ | `validateOnChange` | `boolean` | `false` | Show validation errors as user types |
841
+ | `customValidator` | `function` | - | Custom validation function |
842
+ | `inputLabel` | `string` | - | Label text above the input |
843
+ | `helperText` | `string` | - | Helper text below the input |
844
+ | `keyboardType` | `KeyboardType` | `'default'` | Keyboard type |
845
+ | `secureTextEntry` | `boolean` | `false` | Mask input (for text mode) |
846
+ | `autoFocus` | `boolean` | `true` | Auto-focus input when modal opens |
847
+ | `dismissOnBackdrop` | `boolean` | `false` | Tap backdrop to dismiss (defaults to `false`) |
848
+ | `rounded` | `boolean` | `false` | Enable rounded corners with margins |
849
+
850
+ > [!TIP]
851
+ > Input modals automatically move up when the keyboard appears to keep input fields and buttons visible.
852
+
853
+ ## InputRestrictions
854
+
855
+ | Option | Type | Description |
856
+ | ------------------ | --------- | ------------------------------------------- |
857
+ | `lettersOnly` | `boolean` | Allow only letters (a-zA-Z) |
858
+ | `numbersOnly` | `boolean` | Allow only numbers (0-9) |
859
+ | `alphanumericOnly` | `boolean` | Allow only alphanumeric (a-zA-Z0-9) |
860
+ | `disableCopyPaste` | `boolean` | Disable copy/paste functionality |
861
+ | `uppercase` | `boolean` | Force uppercase input |
862
+ | `lowercase` | `boolean` | Force lowercase input |
863
+ | `minLength` | `number` | Minimum character length |
864
+ | `maxLength` | `number` | Maximum character length |
865
+ | `pattern` | `RegExp` | Custom regex pattern for validation |
866
+ | `patternError` | `string` | Error message when pattern doesn't match |
867
+ | `confirmationText` | `string` | Required text (user must type exactly this) |
868
+ | `caseSensitive` | `boolean` | Case-sensitive confirmation text matching |
869
+ | `trimOnSubmit` | `boolean` | Trim whitespace from value on submit |
870
+
871
+ ## OtpConfig (for OTP/PIN modes)
872
+
873
+ | Option | Type | Default | Description |
874
+ | ----------------------- | --------- | -------------- | ------------------------------------ |
875
+ | `length` | `number` | `6`/`4` | Number of input boxes (6 OTP, 4 PIN) |
876
+ | `masked` | `boolean` | `false`/`true` | Mask input with dots (true for PIN) |
877
+ | `autoSubmit` | `boolean` | `false` | Auto-submit when all boxes filled |
878
+ | `boxWidth` | `number` | `48` | Input box width in pixels |
879
+ | `boxHeight` | `number` | `56` | Input box height in pixels |
880
+ | `boxGap` | `number` | `12` | Gap between boxes in pixels |
881
+ | `boxBorderRadius` | `number` | `12` | Box border radius |
882
+ | `activeBorderColor` | `string` | `#3B82F6` | Focused box border color |
883
+ | `inactiveBorderColor` | `string` | `#D1D5DB` | Unfocused box border color |
884
+ | `filledBackgroundColor` | `string` | `#F3F4F6` | Filled box background color |
885
+ | `textColor` | `string` | `#1F2937` | Text color inside boxes |
886
+ | `fontSize` | `number` | `24` | Font size inside boxes |
887
+
888
+ ## Input Modal Examples
889
+
890
+ ### Delete Confirmation with Text Input
891
+
892
+ ```tsx
893
+ const handleDeleteAccount = async () => {
894
+ const result = await modal.confirmWithText(
895
+ "Delete Account",
896
+ "This action is permanent. Type DELETE to confirm.",
897
+ "DELETE",
898
+ {
899
+ type: "danger",
900
+ confirmText: "Delete Forever",
901
+ restrictions: {
902
+ uppercase: true, // Force uppercase
903
+ caseSensitive: false, // "delete" or "DELETE" both work
904
+ },
905
+ },
906
+ );
907
+
908
+ if (result.confirmed) {
909
+ await deleteUserAccount();
910
+ toast.success("Account deleted");
911
+ }
912
+ };
913
+ ```
914
+
915
+ ### OTP Verification
916
+
917
+ ```tsx
918
+ const handleVerifyEmail = async () => {
919
+ const result = await modal.otp(
920
+ "Verify Your Email",
921
+ "Enter the 6-digit code we sent to you",
922
+ {
923
+ type: "confirm",
924
+ confirmText: "Verify",
925
+ helperText: "Didn't receive the code? Check your spam folder",
926
+ otpConfig: {
927
+ length: 6,
928
+ autoSubmit: true, // Submit automatically when 6 digits entered
929
+ },
930
+ restrictions: {
931
+ numbersOnly: true,
932
+ disableCopyPaste: false, // Allow pasting code
933
+ },
934
+ },
935
+ );
936
+
937
+ if (result.confirmed) {
938
+ const isValid = await verifyOtpCode(result.value);
939
+ if (isValid) {
940
+ toast.success("Email verified!");
941
+ } else {
942
+ toast.error("Invalid code. Please try again.");
943
+ }
944
+ }
945
+ };
946
+ ```
947
+
948
+ ### PIN Entry
949
+
950
+ ```tsx
951
+ const handleEnterPin = async () => {
952
+ const result = await modal.pin(
953
+ "Enter Your PIN",
954
+ "Enter your 4-digit security PIN",
955
+ {
956
+ otpConfig: {
957
+ length: 4,
958
+ masked: true, // Shows dots instead of numbers
959
+ },
960
+ restrictions: {
961
+ numbersOnly: true,
962
+ disableCopyPaste: true, // Prevent copy/paste for security
963
+ },
964
+ },
965
+ );
966
+
967
+ if (result.confirmed) {
968
+ const isCorrect = await validatePin(result.value);
969
+ if (isCorrect) {
970
+ // Proceed with secure action
971
+ }
972
+ }
973
+ };
974
+ ```
975
+
976
+ ### Custom Text Input
977
+
978
+ ```tsx
979
+ const handleTransfer = async () => {
980
+ const result = await modal.input({
981
+ title: "Transfer Funds",
982
+ message: "Enter the amount to transfer",
983
+ inputMode: "text",
984
+ inputLabel: "Amount ($)",
985
+ placeholder: "0.00",
986
+ keyboardType: "decimal-pad",
987
+ restrictions: {
988
+ pattern: /^\d+(\.\d{0,2})?$/,
989
+ patternError: "Please enter a valid amount (e.g., 10.00)",
990
+ maxLength: 10,
991
+ },
992
+ customValidator: (value) => {
993
+ const amount = parseFloat(value);
994
+ if (amount < 1) return "Minimum transfer is $1.00";
995
+ if (amount > 10000) return "Maximum transfer is $10,000.00";
996
+ return null; // Valid
997
+ },
998
+ confirmText: "Transfer",
999
+ type: "confirm",
1000
+ });
1001
+
1002
+ if (result.confirmed) {
1003
+ await processTransfer(parseFloat(result.value));
1004
+ toast.success(`Transferred $${result.value}`);
1005
+ }
1006
+ };
1007
+ ```
1008
+
1009
+ ### Input with Letters Only
1010
+
1011
+ ```tsx
1012
+ const result = await modal.input({
1013
+ title: "Enter Your Name",
1014
+ message: "Please enter your first name",
1015
+ inputLabel: "First Name",
1016
+ placeholder: "John",
1017
+ restrictions: {
1018
+ lettersOnly: true, // Only a-z, A-Z allowed
1019
+ minLength: 2,
1020
+ maxLength: 50,
1021
+ },
1022
+ });
1023
+ ```
1024
+
1025
+ ---
1026
+
715
1027
  ## 📄 License
716
1028
 
717
1029
  MIT © Earl
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import { InputModal as InputModalData } from "./inputModalTypes";
3
+ export interface InputModalProps {
4
+ modal: InputModalData;
5
+ onConfirm: (value: string) => void;
6
+ onCancel: () => void;
7
+ }
8
+ /**
9
+ * Input Modal component with text and OTP input modes
10
+ * Supports various input restrictions and validation options
11
+ */
12
+ export declare const InputModal: React.FC<InputModalProps>;
13
+ //# sourceMappingURL=InputModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputModal.d.ts","sourceRoot":"","sources":["../src/InputModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAiBf,OAAO,EACN,UAAU,IAAI,cAAc,EAM5B,MAAM,mBAAmB,CAAC;AAkC3B,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA02BhD,CAAC"}