Skip to content

Commit

Permalink
💩 keep number selector to remove quick
Browse files Browse the repository at this point in the history
  • Loading branch information
ulricden committed Jul 9, 2024
1 parent 0eed4d4 commit c393f90
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Badge } from './badge/Badge';
import { DateField } from './dateSelector/DateField';
import { DateSelector } from './dateSelector/DateSelector';
import { Label } from './typography/Label';
import { FieldState, NumberField } from './numberField/NumberField';

export { default as Snackbar, useSnackbar } from './alert/Snackbar';
export { default as Banner, useBanner } from './alert/Banner';
Expand All @@ -32,6 +33,8 @@ export {
Screen,
TextField,
TopAppBar,
NumberField,
FieldState,
Card,
Tag,
Divider,
Expand Down
109 changes: 109 additions & 0 deletions src/components/numberField/NumberField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React from 'react';
import { TextInput, StyleSheet, TextInputBase } from 'react-native';
import { useTheme } from '../../styles/themes';
import { NumberValidator } from './NumberValidator';

type FieldBaseProps = React.ComponentProps<typeof TextInputBase>;
export type FieldState = 'filled' | 'filledWithDefault';

export interface NumberFieldProps extends FieldBaseProps {
error: boolean;
fieldState: FieldState;
focused: boolean;
size?: 'm' | 's';
validator?: NumberValidator;
onValueChange?: (value: any) => void;

Check warning on line 15 in src/components/numberField/NumberField.tsx

View workflow job for this annotation

GitHub Actions / unittests / unittests

Unexpected any. Specify a different type
}

export const NumberField = React.forwardRef<TextInput, NumberFieldProps>(
({ error, fieldState, focused, size = 'm', ...props }: NumberFieldProps, ref) => {
const theme = useTheme();

const getCurrentState = () => {
if (error) return 'error';
else if (fieldState === 'filledWithDefault') {
if (focused) return 'prefilled-focused';
else return 'prefilled';
} else if (fieldState === 'filled') {
if (focused) return 'filled-focused';
else return 'filled';
}
return 'prefilled';
};

const stateStyle = () => {
let borderColor = undefined;
let textColor = undefined;
let backgroundColor = undefined;
switch (getCurrentState()) {
case 'prefilled':
textColor = theme.sw.color.neutral[500];
borderColor = undefined;
backgroundColor = theme.sw.color.neutral[200];
break;
case 'filled-focused':
textColor = theme.sw.color.neutral[800];
backgroundColor = theme.sw.color.neutral[0];
borderColor = theme.sw.color.primary[500];
break;
case 'prefilled-focused':
textColor = theme.sw.color.primary[500];
borderColor = theme.sw.color.primary[500];
backgroundColor =
theme.sw.color.primary[500] +
// TODO: use new tokens
'29';
break;
case 'filled':
textColor = theme.sw.color.neutral[800];
borderColor = undefined;
backgroundColor = theme.sw.color.neutral[200];
break;
case 'error':
textColor = theme.sw.color.error[500];
borderColor = undefined;
backgroundColor =
// TODO: use new tokens
theme.sw.color.error[500] + '14';
break;
case undefined:
break;
}

const style = StyleSheet.create({
input: {
borderRadius: size === 's' ? 10 : 18,
height: size === 's' ? 38 : 48,
borderWidth: borderColor !== undefined ? 1 : 0,
borderColor: borderColor,
maxWidth: size === 's' ? 80 : 128,
color: textColor,
fontStyle: 'normal',
fontFamily: 'PublicSans-Bold',
fontSize: size === 's' ? 18 : 20,
lineHeight: size === 's' ? 38 : 48,
backgroundColor: backgroundColor,
paddingVertical: 0,
marginVertical: 0,
},
});
return style.input;
};
return (
<TextInput
{...props}
ref={ref ?? undefined}
style={[stateStyle(), props.style]}
selectionColor={
// TODO: use new tokens
theme.sw.color.primary[500] + '29'
}
cursorColor={theme.sw.color.primary[500]}
keyboardType="number-pad"
textAlign={'center'}
/>
);
},
);

NumberField.displayName = 'NumberField';
68 changes: 68 additions & 0 deletions src/components/numberField/NumberValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* eslint-disable no-useless-escape */
export class NumberValidator {
parser: (value: string) => number;
regex: RegExp;

constructor(
public minValue: number,
public maxValue: number,
public allowDecimal: boolean,
private blockOutrange: boolean = false,
) {
this.parser = allowDecimal ? parseFloat : parseInt;
const decimalRegex =
minValue !== undefined && minValue < 0
? /^-?(0|([1-9]\d*))?([\.]\d?)?$/
: /^(0|([1-9]\d*))?([\.]\d?)?$/;

const integerRegex =
minValue !== undefined && minValue < 0 ? /^-?(0|([1-9]\d*))?$/ : /^(0|([1-9]\d*))?$/;

this.regex = allowDecimal ? decimalRegex : integerRegex;
}

endValidation(text: string | undefined): boolean {
return Boolean(text);
}

allowNegatives(): boolean {
return this.minValue < 0;
}

isAccepted(text: string | undefined): boolean {
return this.validateFormat(text);
}

isValid(text: string | undefined): boolean {
return this.validateMinMax(text);
}

validate(text: string | undefined): boolean {
return this.validateMinMax(text) && this.validateFormat(text);
}

validateFormat(text: string | undefined): boolean {
return (
this.regex.test(text ?? '') && (this.blockOutrange ? this.validateMinMax(text) : true)
);
}

validateMinMax(text: string | undefined): boolean {
if (
!text ||
(text === '-' && this.allowNegatives()) ||
(this.minValue === undefined && this.maxValue === undefined) ||
(text === '.' && this.allowDecimal)
) {
return true;
}

const parsedValue = this.parser(text);
const isValueWithinRange =
!Number.isNaN(parsedValue) &&
(this.minValue !== undefined ? parsedValue >= this.minValue : true) &&
(this.maxValue !== undefined ? parsedValue <= this.maxValue : true);

return isValueWithinRange;
}
}
2 changes: 2 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export {
Screen,
Snackbar,
useSnackbar,
NumberField,
FieldState,
Banner,
useBanner,
TopAppBar,
Expand Down

0 comments on commit c393f90

Please sign in to comment.