Skip to content

Commit

Permalink
InputTime takes formatTime function for custom i18n time string forma…
Browse files Browse the repository at this point in the history
…tting
  • Loading branch information
pixelbandito committed Jul 22, 2020
1 parent fbf0435 commit 988886e
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 20 deletions.
32 changes: 22 additions & 10 deletions src/components/InputTime/AsString.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import styles from './InputTime.module.css';

export interface AsStringProps
extends Omit<InputProps, 'value' | 'max' | 'min'> {
formatTime?: (date: Date) => string;
fuzzyInputProps?: InputProps;
max?: string;
min?: string;
Expand All @@ -40,6 +41,7 @@ export interface AsStringProps
const AsString: React.FC<AsStringProps> = ({
className = '',
disabled,
formatTime,
forwardedRef,
fuzzyInputProps = {},
max,
Expand Down Expand Up @@ -101,7 +103,7 @@ const AsString: React.FC<AsStringProps> = ({

// Fuzzy value is user input.
const [fuzzyValue, setFuzzyValue] = useState(
value ? getLocaleTimeStringFromShortTimeString(value) : ''
value ? getLocaleTimeStringFromShortTimeString(value, { formatTime }) : ''
);

const syncValidity = (
Expand Down Expand Up @@ -142,16 +144,21 @@ const AsString: React.FC<AsStringProps> = ({
};

const handleBlurFuzzyValue = () => {
setFuzzyValue(value ? getLocaleTimeStringFromShortTimeString(value) : '');
setFuzzyValue(
value ? getLocaleTimeStringFromShortTimeString(value, { formatTime }) : ''
);
};

const handleSelectMenuItem = (e: { target: { value: Date } }) => {
const dateTime = e.target.value;

const label = dateTime.toLocaleTimeString([], {
hour: 'numeric',
minute: '2-digit',
});
const label =
typeof formatTime === 'function'
? formatTime(dateTime)
: dateTime.toLocaleTimeString([], {
hour: 'numeric',
minute: '2-digit',
});

const timeString = getShortTimeString(
dateTime.getHours(),
Expand All @@ -170,11 +177,15 @@ const AsString: React.FC<AsStringProps> = ({
}

if (localRef?.current && document.activeElement !== localRef?.current) {
setFuzzyValue(value ? getLocaleTimeStringFromShortTimeString(value) : '');
setFuzzyValue(
value
? getLocaleTimeStringFromShortTimeString(value, { formatTime })
: ''
);
}

syncValidity(shadowTimeInputRef, localRef);
}, [localRef, step, value]);
}, [formatTime, localRef, step, value]);

// Sync validity on min/max changes
useEffect(() => {
Expand Down Expand Up @@ -212,16 +223,17 @@ const AsString: React.FC<AsStringProps> = ({
/>
{showDropdown && (
<Dropdown
toggleAriaLabel={toggleAriaLabel}
className={styles.addons}
disabled={disabled}
formatTime={formatTime}
max={max}
min={min}
value={value}
onSelectMenuItem={handleSelectMenuItem}
showDropdown={showDropdown}
step={dropdownStep}
stepFrom={stepFrom}
toggleAriaLabel={toggleAriaLabel}
value={value}
/>
)}
</div>
Expand Down
24 changes: 19 additions & 5 deletions src/components/InputTime/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import styles from './Dropdown.module.css';
interface DropdownProps {
className?: string;
disabled?: boolean;
formatTime?: (date: Date) => string;
max?: string;
min?: string;
onSelectMenuItem: Function;
Expand All @@ -36,6 +37,7 @@ interface DropdownProps {
const Dropdown: React.FC<DropdownProps> = ({
className = '',
disabled,
formatTime,
max,
min,
onSelectMenuItem,
Expand Down Expand Up @@ -94,10 +96,13 @@ const Dropdown: React.FC<DropdownProps> = ({
do {
attempts += 1;

const label = current.toLocaleTimeString([], {
hour: 'numeric',
minute: '2-digit',
});
const label =
typeof formatTime === 'function'
? formatTime(current)
: current.toLocaleTimeString([], {
hour: 'numeric',
minute: '2-digit',
});

if (
(maxDate === undefined || current <= maxDate) &&
Expand All @@ -116,7 +121,16 @@ const Dropdown: React.FC<DropdownProps> = ({
} while (attempts <= maxAttempts && current < end);

return options;
}, [customStep, max, min, value, onSelectMenuItem, showDropdown, stepFrom]);
}, [
customStep,
formatTime,
max,
min,
onSelectMenuItem,
showDropdown,
stepFrom,
value,
]);

return (
<EasyDropdown
Expand Down
11 changes: 11 additions & 0 deletions src/components/InputTime/story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ storiesOf('Planets/InputTime', module)
value={new Date().toISOString()}
/>
</Wrap>
<Wrap>
<Title>With a custom `formatTime` function</Title>
<InteractiveInput
Component={InputTime}
formatTime={(date: Date) =>
`${date.getHours()}🎈:${date.getMinutes()}🐝`
}
onChange={action('onChange date')}
value={new Date().toISOString()}
/>
</Wrap>
<Wrap>
<Title>Requires you to pick a future date time</Title>
<InteractiveInput
Expand Down
15 changes: 10 additions & 5 deletions src/components/InputTime/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,16 @@ export const getDateTimeFromShortTimeString = (value: string) => {
return date;
};

export const getLocaleTimeStringFromShortTimeString = (value: string) =>
getDateTimeFromShortTimeString(value).toLocaleTimeString([], {
hour: 'numeric',
minute: '2-digit',
});
export const getLocaleTimeStringFromShortTimeString = (
value: string,
{ formatTime }
) =>
typeof formatTime === 'function'
? formatTime(getDateTimeFromShortTimeString(value))
: getDateTimeFromShortTimeString(value).toLocaleTimeString([], {
hour: 'numeric',
minute: '2-digit',
});

export const guessTimeFromString = (string: string) => {
const invalidChars = new RegExp('[^\\d:\\spam.]', 'gi');
Expand Down

0 comments on commit 988886e

Please sign in to comment.