web-ridge / react-native-paper-dates

Smooth and fast cross platform Material Design date and time picker for React Native Paper
https://www.reactnativepaperdates.com
MIT License
662 stars 170 forks source link

Introduce auto slashes to text input. #269

Closed iM-GeeKy closed 1 year ago

iM-GeeKy commented 1 year ago

@RichardLindhout Please test this out and make sure it works how we discussed. @jpatricksweeney This isn't quite ready yet. It doesn't accommodate all scenarios. You might be able to use patch-package to apply this temporarily since not everyone uses the slash in there date representation.

NOTE - Invalid dates of 00/00/0000 and 99/99/9999 can be input, but it doesn't cause any issues. The validation seems to gracefully handle this scenario.

RichardLindhout commented 1 year ago

It’s not always slashes in my language it’s a - sign the code before was detecting that sign automatically is it possible to get that back in too?

iM-GeeKy commented 1 year ago

It’s not always slashes in my language it’s a - sign the code before was detecting that sign automatically is it possible to get that back in too?

Ahh great point. I didn't even think of that 🤦🏼 and I don't believe we ever ripped out that code, but I guess it stopped working at some point?

I see your enhanceTextWithMask function, but it's only being called on blur. I don't recall it ever auto-correcting on change, but I also haven't worked on this very long.

It turns out the functionality was removed in this pull request. If we reintroduce that functionality we will effectively be reopening the issue associated with the pull request.

iM-GeeKy commented 1 year ago

@jpatricksweeney here is the patch i'm currently using in my personal project for this fix using patch-package. This fix works for english, but unfortunately isn't robust enough since not everyone uses "/" (some use "-"). I plan on looking into a proper solution which will be merged into the branch when ready.

diff --git a/node_modules/react-native-paper-dates/src/TextInputMask.tsx b/node_modules/react-native-paper-dates/src/TextInputMask.tsx
index e8e99e1..58bfc26 100644
--- a/node_modules/react-native-paper-dates/src/TextInputMask.tsx
+++ b/node_modules/react-native-paper-dates/src/TextInputMask.tsx
@@ -82,10 +82,30 @@ function TextInputWithMask(
   )

   const onInnerChange = (text: string) => {
-    if (text.length === mask.length) {
-      onChangeText && onChangeText(text)
+    let trimmedText = text.trim()
+    const format = 'mm/dd/yyyy'
+    const match = new RegExp(
+      format
+        .replace(/(\w+)\W(\w+)\W(\w+)/, '^\\s*($1)\\W*($2)?\\W*($3)?([0-9]*).*')
+        .replace(/m|d|y/g, '\\d')
+    )
+    const replaceValue = format.match(/\W/)
+    const replace = '$1/$2/$3$4'.replace(/\//g, (replaceValue ?? '') as string)
+
+    const isBackSpace = controlledValue.length > trimmedText.length
+
+    if (!isBackSpace) {
+      trimmedText = trimmedText
+        .replace(/(^|\W)(?=\d\W)/g, '$10')
+        .replace(match, replace)
+        .replace(/(\W)+/g, '$1')
     }
-    setControlledValue(text)
+
+    if (trimmedText.length === mask.length) {
+      onChangeText && onChangeText(trimmedText)
+    }
+
+    setControlledValue(trimmedText)
   }

   const onInnerBlur = () => {
@@ -107,6 +127,7 @@ function TextInputWithMask(
       onChange={(e) => {
         onChange && onChange(e)
       }}
+      maxLength={10}
       onBlur={onInnerBlur}
     />
   )
iM-GeeKy commented 1 year ago

@RichardLindhout When you get a chance can you check this out? I parameterized the mask, so it should work with any locale and any split character. The idea was a hybrid approach with your existing implementation, but using regular expressions instead of having to double loop.

RichardLindhout commented 1 year ago

Nice!

RichardLindhout commented 1 year ago

Great work @iM-GeeKy !