From c6504eadc237377c44b317986561dc525ad01a0d Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Tue, 26 Nov 2019 18:02:58 -0500 Subject: [PATCH] feat(textinputwithbadges): adds input value as badge on blur --- .../components/TextInputWithBadges.tsx | 19 ++++++++ .../stories/TextInputWithBadges.stories.tsx | 13 ++++++ .../tests/TextInputWithBadges.test.tsx | 46 ++++++++++++++++++- .../TextInputWithBadges.test.tsx.snap | 3 ++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/packages/textInput/components/TextInputWithBadges.tsx b/packages/textInput/components/TextInputWithBadges.tsx index 0764bfea0..cde61ccbe 100644 --- a/packages/textInput/components/TextInputWithBadges.tsx +++ b/packages/textInput/components/TextInputWithBadges.tsx @@ -22,6 +22,7 @@ import { TextInputWithIconProps } from "./TextInputWithIcon"; import { TextInputWithIcon } from ".."; import { BadgeAppearance } from "../../badge/components/badge"; import { StateChangeOptions } from "downshift"; +import { InputAppearance } from "../../shared/types/inputAppearance"; export interface BadgeDatum { value: string; @@ -39,6 +40,7 @@ interface TextInputWithBadgesProps extends TextInputWithIconProps { cb?: () => void ) => void; badgeAppearance?: BadgeAppearance; + addBadgeOnBlur?: boolean; } export const getStringAsBadgeDatum = ( @@ -52,6 +54,12 @@ export class TextInputWithBadges extends TextInputWithIcon< TextInputWithBadgesProps, {} > { + public static defaultProps: Partial = { + type: "text", + appearance: InputAppearance.Standard, + showInputLabel: true, + addBadgeOnBlur: true + }; private inputRef = React.createRef(); constructor(props) { @@ -59,6 +67,7 @@ export class TextInputWithBadges extends TextInputWithIcon< this.handleKeyUp = this.handleKeyUp.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); + this.handleBlur = this.handleBlur.bind(this); this.handleTagAdd = this.handleTagAdd.bind(this); this.handleTagDelete = this.handleTagDelete.bind(this); } @@ -69,10 +78,12 @@ export class TextInputWithBadges extends TextInputWithIcon< badges, onBadgeChange, downshiftReset, + addBadgeOnBlur, ...inputProps } = baseProps as TextInputWithBadgesProps; inputProps.onKeyDown = this.handleKeyDown; inputProps.onKeyUp = this.handleKeyUp; + inputProps.onBlur = this.handleBlur.bind(this, inputProps.onBlur); inputProps.type = "text"; inputProps.ref = this.inputRef; return inputProps; @@ -195,6 +206,14 @@ export class TextInputWithBadges extends TextInputWithIcon< } } + private handleBlur(cb, e) { + cb(e); // calls the onBlur handler from the component this extends + + if (this.props.addBadgeOnBlur) { + this.handleTagAdd(getStringAsBadgeDatum(e.target.value)); + } + } + private onBadgeClose(clickedTag) { this.handleTagDelete(clickedTag); } diff --git a/packages/textInput/stories/TextInputWithBadges.stories.tsx b/packages/textInput/stories/TextInputWithBadges.stories.tsx index c6bf5fb33..4ede9c9b6 100644 --- a/packages/textInput/stories/TextInputWithBadges.stories.tsx +++ b/packages/textInput/stories/TextInputWithBadges.stories.tsx @@ -73,6 +73,19 @@ storiesOf("Forms/TextInputWithBadges", module) )} )) + .add("don't add badge on blur", () => ( + + {({ badges, badgeChangeHandler }) => ( + + )} + + )) .add("used w/ a Typeahead", () => ( {({ diff --git a/packages/textInput/tests/TextInputWithBadges.test.tsx b/packages/textInput/tests/TextInputWithBadges.test.tsx index 2bd6f1f19..0313855af 100644 --- a/packages/textInput/tests/TextInputWithBadges.test.tsx +++ b/packages/textInput/tests/TextInputWithBadges.test.tsx @@ -76,13 +76,57 @@ describe("TextInputWithBadges", () => { key: "Enter" }); - // TODO: change this if I decide not to "sanitize" the `value` string expect(badgeChangeHandler).toHaveBeenCalledWith( [getStringAsBadgeDatum(inputValue)], getStringAsBadgeDatum(inputValue) ); }); + it("calls onBadgeChange with the badge data and input value when the input blurs", () => { + const badgeChangeHandler = jest.fn(); + const inputValue = "some value"; + const component = mount( + + ); + + expect(badgeChangeHandler).not.toHaveBeenCalled(); + component.find("input").simulate("focus"); + component.find("input").simulate("blur"); + + expect(badgeChangeHandler).toHaveBeenCalledWith( + [getStringAsBadgeDatum(inputValue)], + getStringAsBadgeDatum(inputValue) + ); + }); + + it("does not call onBadgeChange with the badge data and input value when the input blurs if addBadgeOnBlur=false", () => { + const badgeChangeHandler = jest.fn(); + const inputValue = "some value"; + const component = mount( + + ); + + expect(badgeChangeHandler).not.toHaveBeenCalled(); + component.find("input").simulate("focus"); + component.find("input").simulate("blur"); + + expect(badgeChangeHandler).not.toHaveBeenCalledWith( + [getStringAsBadgeDatum(inputValue)], + getStringAsBadgeDatum(inputValue) + ); + }); + it("does not call onBadgeChange when keying enter if the input value is undefined", () => { const badgeChangeHandler = jest.fn(); const component = mount( diff --git a/packages/textInput/tests/__snapshots__/TextInputWithBadges.test.tsx.snap b/packages/textInput/tests/__snapshots__/TextInputWithBadges.test.tsx.snap index 6de4814a2..1acf2502c 100644 --- a/packages/textInput/tests/__snapshots__/TextInputWithBadges.test.tsx.snap +++ b/packages/textInput/tests/__snapshots__/TextInputWithBadges.test.tsx.snap @@ -285,6 +285,7 @@ exports[`TextInputWithBadges renders badges with custom BadgeAppearance 1`] = ` }