Skip to content

Commit

Permalink
[ft request] Add extra UX affordance for pasting to not require the e…
Browse files Browse the repository at this point in the history
…nter key

requires an early return on `onChange` - onPaste fires before onChange, and onChange will bogart the state updates otherwise
  • Loading branch information
cee-chen committed Nov 3, 2023
1 parent 02fa161 commit 78a0bf1
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,30 @@ describe('EuiAbsoluteTab', () => {
fireEvent.keyDown(input, { key: 'Enter' });
expect(queryByText(formatHelpText)).toHaveClass('euiFormErrorText');
});

it('immediately parses pasted text without needing an extra enter keypress', () => {
const { getByTestSubject, queryByText } = render(
<EuiAbsoluteTab {...props} />
);
const input = getByTestSubject(
'superDatePickerAbsoluteDateInput'
) as HTMLInputElement;

fireEvent.paste(input, {
clipboardData: { getData: () => '1970-01-01' },
});
expect(input).not.toBeInvalid();
expect(input.value).toContain('Jan 1, 1970');

input.value = '';
fireEvent.paste(input, {
clipboardData: { getData: () => 'not a date' },
});
expect(input).toBeInvalid();

expect(queryByText(/Allowed formats: /)).toBeInTheDocument();
expect(queryByText(/Press the Enter key /)).not.toBeInTheDocument();
});
});

describe('date parsing', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Side Public License, v 1.
*/

import React, { Component, ChangeEvent, KeyboardEvent } from 'react';
import React, { Component, ChangeEvent } from 'react';

import moment, { Moment, LocaleSpecifier } from 'moment'; // eslint-disable-line import/named

Expand Down Expand Up @@ -52,6 +52,7 @@ export class EuiAbsoluteTab extends Component<
EuiAbsoluteTabState
> {
state: EuiAbsoluteTabState;
isParsing = false; // Store outside of state as a ref for faster/unbatched updates

constructor(props: EuiAbsoluteTabProps) {
super(props);
Expand Down Expand Up @@ -89,27 +90,32 @@ export class EuiAbsoluteTab extends Component<
};

handleTextChange = (event: ChangeEvent<HTMLInputElement>) => {
if (this.isParsing) return;

this.setState({
textInputValue: event.target.value,
hasUnparsedText: true,
isTextInvalid: false,
});
};

parseUserDateInput = (event: KeyboardEvent<HTMLInputElement>) => {
if (event.key !== keys.ENTER) return;

const { onChange, dateFormat } = this.props;
const { textInputValue } = this.state;
parseUserDateInput = (textInputValue: string) => {
this.isParsing = true;
const finishParsing = () => {
this.isParsing = false;
};

const invalidDateState = {
textInputValue,
isTextInvalid: true,
valueAsMoment: null,
};
if (!textInputValue) {
return this.setState(invalidDateState);
return this.setState(invalidDateState, finishParsing);
}

const { onChange, dateFormat } = this.props;

// Attempt to parse with passed `dateFormat`
let valueAsMoment = moment(textInputValue, dateFormat, true);
let dateIsValid = valueAsMoment.isValid();
Expand All @@ -122,14 +128,17 @@ export class EuiAbsoluteTab extends Component<

if (dateIsValid) {
onChange(valueAsMoment.toISOString());
this.setState({
textInputValue: valueAsMoment.format(this.props.dateFormat),
valueAsMoment: valueAsMoment,
hasUnparsedText: false,
isTextInvalid: false,
});
this.setState(
{
textInputValue: valueAsMoment.format(this.props.dateFormat),
valueAsMoment: valueAsMoment,
hasUnparsedText: false,
isTextInvalid: false,
},
finishParsing
);
} else {
this.setState(invalidDateState);
this.setState(invalidDateState, finishParsing);
}
};

Expand Down Expand Up @@ -181,7 +190,14 @@ export class EuiAbsoluteTab extends Component<
isInvalid={isTextInvalid}
value={textInputValue}
onChange={this.handleTextChange}
onKeyDown={this.parseUserDateInput}
onPaste={(event) => {
this.parseUserDateInput(event.clipboardData.getData('text'));
}}
onKeyDown={(event) => {
if (event.key === keys.ENTER) {
this.parseUserDateInput(textInputValue);
}
}}
data-test-subj="superDatePickerAbsoluteDateInput"
prepend={<EuiFormLabel>{labelPrefix}</EuiFormLabel>}
/>
Expand Down

0 comments on commit 78a0bf1

Please sign in to comment.