Skip to content

Commit

Permalink
Add text inputs.
Browse files Browse the repository at this point in the history
  • Loading branch information
jameswilddev committed Nov 24, 2021
1 parent aa9cd08 commit c81be37
Show file tree
Hide file tree
Showing 8 changed files with 1,627 additions and 0 deletions.
103 changes: 103 additions & 0 deletions components/createNullableTextInputComponent/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import * as React from "react";
import type { ControlStyle } from "../..";
import { createInputComponent } from "../createInputComponent";

/**
* Creates a new input component pre-configured as a nullable text input.
* @param controlStyle The style of the component to create.
* @param leftIcon The icon to show on the left side, if any, else, null.
* @param rightIcon The icon to show on the right side, if any, else, null.
* @param minimumLength When non-null, entered values must be greater for
* validation to succeed.
* @param maximumLength When non-null, entered values must be greater or equal
* for validation to succeed.
* @returns The created component.
*/
export const createNullableTextInputComponent = (
controlStyle: ControlStyle,
leftIcon: null | React.ReactNode | JSX.Element,
rightIcon: null | React.ReactNode | JSX.Element,
minimumLength: null | number,
maximumLength: null | number
): React.FunctionComponent<{
/**
* The value to edit. When undefined, it is treated as an invalid empty
* string.
*/
readonly value: undefined | null | string;

/**
* Invoked when the user edits the text in the box.
* @param parsed The value parsed, or undefined should it not be parseable.
* @param complete True when the user has finished editing, otherwise, false.
*/
onChange(parsed: undefined | null | string, complete: boolean): void;

/**
* When true, the text box is rendered semi-transparently and does not accept
* focus or input.
*/
readonly disabled: boolean;

/**
* Text to be shown when no value has been entered.
*/
readonly placeholder: string;

/**
* The value entered must not appear in this list.
*/
readonly unique: ReadonlyArray<string>;
}> => {
const NullableTextInputComponent = createInputComponent<
null | string,
ReadonlyArray<string>
>(
(value) => (value === null ? `` : value.trim().replace(/\s+/g, ` `)),
(unparsed, context) => {
if (unparsed.trim() === ``) {
return null;
} else {
const parsed = unparsed.trim().replace(/\s+/g, ` `);

if (minimumLength !== null && parsed.length < minimumLength) {
return undefined;
} else if (maximumLength !== null && parsed.length > maximumLength) {
return undefined;
} else {
const match = parsed.toLowerCase();

for (const option of context) {
if (option.trim().replace(/\s+/g, ` `).toLowerCase() === match) {
return undefined;
}
}

return parsed;
}
}
},
controlStyle,
false,
`off`,
`default`,
false,
false
);

return ({ value, onChange, disabled, placeholder, unique }) => (
<NullableTextInputComponent
leftIcon={leftIcon}
rightIcon={rightIcon}
value={value}
onChange={onChange}
disabled={disabled}
placeholder={placeholder}
context={unique}
secureTextEntry={false}
onSubmit={() => {
/* No-op. */
}}
/>
);
};
113 changes: 113 additions & 0 deletions components/createNullableTextInputComponent/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# `react-native-app-helpers/createNullableTextInputComponent`

Creates a new input component pre-configured as a nullable text input.

## Usage

```tsx
import { createNullableTextInputComponent } from "react-native-app-helpers";

const ExampleInput = createNullableTextInputComponent(
{
fontFamily: `Example Font Family`,
fontSize: 37,
paddingVertical: 12,
paddingHorizontal: 29,
blurredValid: {
textColor: `#FFEE00`,
placeholderColor: `#E7AA32`,
backgroundColor: `#32AE12`,
radius: 5,
border: {
width: 4,
color: `#FF00FF`,
},
},
blurredInvalid: {
textColor: `#99FE88`,
placeholderColor: `#CACA3A`,
backgroundColor: `#259284`,
radius: 10,
border: {
width: 6,
color: `#9A9A8E`,
},
},
focusedValid: {
textColor: `#55EA13`,
placeholderColor: `#273346`,
backgroundColor: `#CABA99`,
radius: 3,
border: {
width: 5,
color: `#646464`,
},
},
focusedInvalid: {
textColor: `#ABAADE`,
placeholderColor: `#47ADAD`,
backgroundColor: `#32AA88`,
radius: 47,
border: {
width: 12,
color: `#98ADAA`,
},
},
disabledValid: {
textColor: `#AE2195`,
placeholderColor: `#FFAAEE`,
backgroundColor: `#772728`,
radius: 100,
border: {
width: 14,
color: `#5E5E5E`,
},
},
disabledInvalid: {
textColor: `#340297`,
placeholderColor: `#233832`,
backgroundColor: `#938837`,
radius: 2,
border: {
width: 19,
color: `#573829`,
},
},
},
<Text>Shown to the left</Text>,
<Text>Shown to the right</Text>,
null,
-14,
null,
3,
);

const ExampleScreen = () => {
// Useful for realtime submit button updates.
const [incompleteValue, setIncompleteValue] = React.useState<undefined | null | number>(undefined);

// Useful for persistence.
const [completeValue, setCompleteValue] = React.useState<undefined | null | number>(undefined);

return (
<React.Fragment>
<ExampleInput
value={incompleteValue}
onChange={(value, complete) => {
if (complete) {
setCompleteValue(value);
} else {
setIncompleteValue(value);
}
}}
disabled={false}
placeholder="Shown when no text has been entered"
unique={[`Not`, `In`, `This`, `List`]}
/>
<Text>Incomplete: {incompleteValue}</Text>
<Text>Complete: {completeValue}</Text>
<Text>Submitted: {submittedValue}</Text>
</React.Fragment>
);
}
```
Loading

0 comments on commit c81be37

Please sign in to comment.