From 48f2583e7c05e8d3e0bed3c462876e9a254beb8c Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Tue, 13 Aug 2019 19:58:25 +0900 Subject: [PATCH 1/8] #289 Lookup: mv .js -> .tsx --- src/scripts/{Lookup.js => Lookup.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/scripts/{Lookup.js => Lookup.tsx} (100%) diff --git a/src/scripts/Lookup.js b/src/scripts/Lookup.tsx similarity index 100% rename from src/scripts/Lookup.js rename to src/scripts/Lookup.tsx From f478471e1b729ed0608434c1ac36e6ce398b6495 Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Mon, 19 Aug 2019 20:52:59 +0900 Subject: [PATCH 2/8] #289 Lookup: Convert PropTypes to TypeScript types --- src/scripts/Lookup.tsx | 322 ++++++++++++++++++++++------------------- src/scripts/Pill.tsx | 2 +- 2 files changed, 176 insertions(+), 148 deletions(-) diff --git a/src/scripts/Lookup.tsx b/src/scripts/Lookup.tsx index b481b5669..c401adcc8 100644 --- a/src/scripts/Lookup.tsx +++ b/src/scripts/Lookup.tsx @@ -1,10 +1,9 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import classnames from 'classnames'; -import { autoAlign } from './AutoAlign'; -import { FormElement } from './FormElement'; +import { autoAlign, InjectedProps } from './AutoAlign'; +import { FormElement, FormElementProps } from './FormElement'; import { Input } from './Input'; -import { Icon } from './Icon'; +import { Icon, IconCategory } from './Icon'; import { Spinner } from './Spinner'; import { Pill } from './Pill'; import { DropdownButton } from './DropdownButton'; @@ -14,27 +13,29 @@ import { uuid, isElInChildren, registerStyle } from './util'; /** * */ -const LookupEntryType = PropTypes.shape({ - category: PropTypes.string, - icon: PropTypes.string, - label: PropTypes.string, - value: PropTypes.string, - meta: PropTypes.string, -}); +export type LookupEntry = { + category: IconCategory; + icon: string; + label: string; + value: string; + meta: string; +}; + +export type LookupSelectionProps = { + id?: string; + selected?: LookupEntry; + hidden?: boolean; + onResetSelection?: (e?: any) => void; + lookupSelectionRef?: (node: HTMLDivElement) => void; +}; /** * */ -export class LookupSelection extends Component { - static propTypes = { - id: PropTypes.string, - selected: LookupEntryType, - hidden: PropTypes.bool, - onResetSelection: PropTypes.func, - lookupSelectionRef: PropTypes.func, - }; +export class LookupSelection extends Component { + private pill: HTMLElement | null = null; - onKeyDown(e) { + onKeyDown(e: any) { if (e.keyCode === 8 || e.keyCode === 46) { // Bacspace / DEL e.preventDefault(); @@ -45,8 +46,8 @@ export class LookupSelection extends Component { } } - renderPill(selected) { - const onPillClick = (e) => { + renderPill(selected: LookupEntry) { + const onPillClick = (e: any) => { e.target.focus(); e.preventDefault(); e.stopPropagation(); @@ -86,41 +87,41 @@ export class LookupSelection extends Component { } } -/** - * - */ -const ICON_ALIGNS = ['left', 'right']; +type LookupScope = { + label: string; + value: string; + icon: string; +}; + +export type LookupSearchProps = { + id?: string; + className?: string; + hidden?: boolean; + searchText?: string; + scopes?: LookupScope[]; + targetScope?: any; + iconAlign?: 'left' | 'right'; + disabled?: boolean; + onKeyDown?: (e: any) => void; + onBlur?: (e: any) => void; + onChange?: (searchText: string) => void; + onScopeMenuClick?: (e: any) => void; + onScopeChange?: (value: string) => void; + onPressDown?: () => void; + onSubmit?: () => void; + onComplete?: (cancel?: boolean) => void; + lookupSearchRef?: (node: HTMLDivElement) => void; +}; /** * */ -export class LookupSearch extends Component { - static propTypes = { - className: PropTypes.string, - hidden: PropTypes.bool, - searchText: PropTypes.string, - scopes: PropTypes.arrayOf( - PropTypes.shape({ - label: PropTypes.string, - value: PropTypes.string, - icon: PropTypes.string, - }) - ), - targetScope: PropTypes.any, // eslint-disable-line - iconAlign: PropTypes.oneOf(ICON_ALIGNS), - disabled: PropTypes.bool, - onKeyDown: PropTypes.func, - onBlur: PropTypes.func, - onChange: PropTypes.func, - onScopeMenuClick: PropTypes.func, - onScopeChange: PropTypes.func, - onPressDown: PropTypes.func, - onSubmit: PropTypes.func, - onComplete: PropTypes.func, - lookupSearchRef: PropTypes.func, - }; +export class LookupSearch extends Component { + private input: HTMLInputElement | null = null; - constructor(props) { + private node: HTMLDivElement | null = null; + + constructor(props: Readonly) { super(props); /* eslint-disable max-len */ registerStyle('lookupSearch', [ @@ -152,18 +153,22 @@ export class LookupSearch extends Component { } onLookupIconClick = () => { - this.props.onSubmit(); + if (this.props.onSubmit) { + this.props.onSubmit(); + } }; - onInputKeyDown = (e) => { + onInputKeyDown = (e: any) => { if (e.keyCode === 13) { // return key e.preventDefault(); e.stopPropagation(); const searchText = e.target.value; if (searchText) { - this.props.onSubmit(); - } else { + if (this.props.onSubmit) { + this.props.onSubmit(); + } + } else if (this.props.onComplete) { // if no search text, quit lookup search this.props.onComplete(); } @@ -171,26 +176,32 @@ export class LookupSearch extends Component { // down key e.preventDefault(); e.stopPropagation(); - this.props.onPressDown(); + if (this.props.onPressDown) { + this.props.onPressDown(); + } } else if (e.keyCode === 27) { // ESC e.preventDefault(); e.stopPropagation(); // quit lookup search (cancel) const cancel = true; - this.props.onComplete(cancel); + if (this.props.onComplete) { + this.props.onComplete(cancel); + } } if (this.props.onKeyDown) { this.props.onKeyDown(e); } }; - onInputChange = (e) => { + onInputChange = (e: any) => { const searchText = e.target.value; - this.props.onChange(searchText); + if (this.props.onChange) { + this.props.onChange(searchText); + } }; - onInputBlur = (e) => { + onInputBlur = (e: any) => { setTimeout(() => { if (!this.isFocusedInComponent()) { if (this.props.onBlur) { @@ -200,19 +211,19 @@ export class LookupSearch extends Component { }, 10); }; - onScopeMenuClick = (e) => { + onScopeMenuClick = (e: any) => { if (this.props.onScopeMenuClick) { this.props.onScopeMenuClick(e); } }; - onMenuItemClick = (scope) => { + onMenuItemClick = (scope: LookupScope) => { if (this.props.onScopeChange) { this.props.onScopeChange(scope.value); } }; - handleLookupSearchRef = (node) => { + handleLookupSearchRef = (node: HTMLDivElement) => { this.node = node; const { lookupSearchRef } = this.props; if (lookupSearchRef) { @@ -224,7 +235,7 @@ export class LookupSearch extends Component { return isElInChildren(this.node, document.activeElement); } - renderSearchInput(props) { + renderSearchInput(props: any) { const { className, hidden, searchText, iconAlign = 'right' } = props; const searchInputClassNames = classnames( 'slds-grid', @@ -274,7 +285,7 @@ export class LookupSearch extends Component { ); } - renderScopeSelector({ scopes, targetScope: target, disabled }) { + renderScopeSelector({ scopes, targetScope: target, disabled }: any) { let targetScope = scopes[0] || {}; for (const scope of scopes) { if (scope.value === target) { @@ -298,7 +309,7 @@ export class LookupSearch extends Component { onMenuItemClick={this.onMenuItemClick} onBlur={this.onInputBlur} > - {scopes.map((scope) => ( + {scopes.map((scope: LookupScope) => ( ))} @@ -317,9 +328,9 @@ export class LookupSearch extends Component { { 'slds-hide': hidden } ); const styles = { - WebkitFlexWrap: 'nowrap', + WebkitFlexWrap: 'nowrap' as const, msFlexWrap: 'nowrap', - flexWrap: 'nowrap', + flexWrap: 'nowrap' as const, }; return (
LookupEntry; + listRef?: (node: HTMLDivElement) => void; + onSelect?: (entry: LookupEntry | null) => void; + onBlur?: (e: React.FocusEvent) => void; + header?: JSX.Element; + footer?: JSX.Element; +} & InjectedProps; + /** * */ -class LookupCandidateList extends Component { - static propTypes = { - data: PropTypes.arrayOf(LookupEntryType), - focus: PropTypes.bool, - loading: PropTypes.bool, - filter: PropTypes.func, - align: PropTypes.oneOf(['left', 'right']), - vertAlign: PropTypes.oneOf(['top', 'bottom']), - listRef: PropTypes.func, - onSelect: PropTypes.func, - onBlur: PropTypes.func, - header: PropTypes.node, - footer: PropTypes.node, - }; +class LookupCandidateList extends Component { + private node: HTMLDivElement | null = null; componentDidMount() { if (this.props.focus) { @@ -365,7 +376,7 @@ class LookupCandidateList extends Component { } } - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: Readonly) { if (this.props.focus && !prevProps.focus) { setTimeout(() => { this.focusToTargetItemEl(0); @@ -373,13 +384,13 @@ class LookupCandidateList extends Component { } } - onSelect(entry) { + onSelect(entry: LookupEntry | null) { if (this.props.onSelect) { this.props.onSelect(entry); } } - onKeyDown(e) { + onKeyDown(e: any) { if (e.keyCode === 38 || e.keyCode === 40) { // UP/DOWN e.preventDefault(); @@ -405,18 +416,20 @@ class LookupCandidateList extends Component { } } - focusToTargetItemEl(index) { + focusToTargetItemEl(index: number) { const el = this.node; if (!el) { return; } - const anchors = el.querySelectorAll('.react-slds-candidate[tabIndex]'); + const anchors = el.querySelectorAll( + '.react-slds-candidate[tabIndex]' + ); if (anchors[index]) { anchors[index].focus(); } } - renderCandidate(entry) { + renderCandidate(entry: LookupEntry) { const { category, icon, label, value, meta } = entry; return (
  • @@ -480,7 +493,7 @@ class LookupCandidateList extends Component { ...(vertAlign === 'bottom' ? { bottom: '100%' } : {}), ...(align === 'right' ? { left: 'auto', right: 0 } : {}), }; - const handleDOMRef = (node) => { + const handleDOMRef = (node: HTMLDivElement) => { this.node = node; if (listRef) { listRef(node); @@ -524,60 +537,74 @@ export const LookupCandidateListPortal = autoAlign({ triggerSelector: '.slds-lookup', })(LookupCandidateList); +export type LookupProps = { + id?: string; + className?: string; + label?: string; + required?: boolean; + error?: FormElementProps['error']; + + value?: string; + defaultValue?: string; + + selected?: LookupEntry; + defaultSelected?: LookupEntry; + + opened?: boolean; + defaultOpened?: boolean; + + searchText?: string; + defaultSearchText?: string; + + loading?: boolean; + data?: LookupEntry[]; + lookupFilter?: ( + entry: LookupEntry, + searchText?: string, + targetScope?: string + ) => LookupEntry; + listHeader?: JSX.Element; + listFooter?: JSX.Element; + scopes?: LookupScope[]; + targetScope?: string; + defaultTargetScope?: string; + iconAlign?: 'left' | 'right'; + totalCols?: number; + cols?: number; + + onSearchTextChange?: (searchText: string) => void; + onScopeMenuClick?: (e: any) => void; + onScopeChange?: (targetScope: string) => void; + onLookupRequest?: (searchText?: string) => void; + onBlur?: () => void; + onSelect?: (e: any) => void; + onComplete?: (cancel?: boolean) => void; +}; + +export type LookupState = { + id: string; + selected?: LookupEntry | null; + opened?: boolean; + searchText?: string; + targetScope?: string; + focusFirstCandidate: boolean; +}; /** * */ -export default class Lookup extends Component { - static propTypes = { - id: PropTypes.string, - className: PropTypes.string, - label: PropTypes.string, - required: PropTypes.bool, - // FormElement.propTypes.error - error: PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.string, - PropTypes.shape({ - message: PropTypes.string, - }), - ]), - value: PropTypes.string, - defaultValue: PropTypes.string, - selected: LookupEntryType, - defaultSelected: LookupEntryType, - opened: PropTypes.bool, - defaultOpened: PropTypes.bool, - searchText: PropTypes.string, - defaultSearchText: PropTypes.string, - loading: PropTypes.bool, - data: PropTypes.arrayOf(LookupEntryType), - lookupFilter: PropTypes.func, - listHeader: PropTypes.node, - listFooter: PropTypes.node, - scopes: PropTypes.arrayOf( - PropTypes.shape({ - label: PropTypes.string, - value: PropTypes.string, - icon: PropTypes.string, - }) - ), - targetScope: PropTypes.string, - iconAlign: PropTypes.oneOf(ICON_ALIGNS), - defaultTargetScope: PropTypes.string, - onSearchTextChange: PropTypes.func, - onScopeMenuClick: PropTypes.func, - onScopeChange: PropTypes.func, - onLookupRequest: PropTypes.func, - onBlur: PropTypes.func, - onSelect: PropTypes.func, - onComplete: PropTypes.func, - totalCols: PropTypes.number, - cols: PropTypes.number, - }; - +export default class Lookup extends Component { static isFormElement = true; - constructor(props) { + private node: HTMLDivElement | null = null; + + private selection: HTMLDivElement | null = null; + + private candidateList: HTMLDivElement | null = null; + + // eslint-disable-next-line react/sort-comp + private search: any; + + constructor(props: Readonly) { super(props); this.state = { id: `form-element-${uuid()}`, @@ -589,28 +616,28 @@ export default class Lookup extends Component { }; } - onScopeMenuClick(e) { + onScopeMenuClick(e: any) { this.setState({ opened: false }); if (this.props.onScopeMenuClick) { this.props.onScopeMenuClick(e); } } - onScopeChange(targetScope) { + onScopeChange(targetScope: string) { this.setState({ targetScope }); if (this.props.onScopeChange) { this.props.onScopeChange(targetScope); } } - onSearchTextChange(searchText) { + onSearchTextChange(searchText: string) { this.setState({ searchText }); if (this.props.onSearchTextChange) { this.props.onSearchTextChange(searchText); } } - onLookupRequest(searchText) { + onLookupRequest(searchText?: string) { this.setState({ opened: true }); if (this.props.onLookupRequest) { this.props.onLookupRequest(searchText); @@ -634,7 +661,7 @@ export default class Lookup extends Component { }, 10); } - onLookupItemSelect(selected) { + onLookupItemSelect(selected: LookupEntry | null) { if (selected) { this.setState({ selected, opened: false }); if (this.props.onSelect) { @@ -721,7 +748,7 @@ export default class Lookup extends Component { className ); const formElemProps = { id, totalCols, cols, label, required, error }; - /* eslint-disable no-unused-vars */ + /* eslint-disable @typescript-eslint/no-unused-vars */ const { defaultSelected, defaultOpened, @@ -735,7 +762,7 @@ export default class Lookup extends Component { onLookupRequest, ...searchProps } = props; - /* eslint-enable no-unused-vars */ + /* eslint-enable @typescript-eslint/no-unused-vars */ return ( (this.node = node)} @@ -780,7 +807,8 @@ export default class Lookup extends Component { loading={loading} filter={ lookupFilter - ? (entry) => lookupFilter(entry, searchText, targetScope) + ? (entry: LookupEntry) => + lookupFilter(entry, searchText, targetScope) : undefined } header={listHeader} diff --git a/src/scripts/Pill.tsx b/src/scripts/Pill.tsx index de3277b4c..d1e5d73c8 100644 --- a/src/scripts/Pill.tsx +++ b/src/scripts/Pill.tsx @@ -14,7 +14,7 @@ export type PillProps = { category?: IconCategory; icon?: string; }; - pillRef?: (node?: HTMLElement) => void; + pillRef?: (node: HTMLElement) => void; onClick?: (e: React.MouseEvent) => void; onRemove?: (e: any) => void; }; From 29c785f3fd398f7ef52db8c88afc3be3c7bf9a38 Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Mon, 19 Aug 2019 20:55:14 +0900 Subject: [PATCH 3/8] #289 Lookup: mv story .js -> .tsx --- stories/{LookupStories.js => LookupStories.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename stories/{LookupStories.js => LookupStories.tsx} (100%) diff --git a/stories/LookupStories.js b/stories/LookupStories.tsx similarity index 100% rename from stories/LookupStories.js rename to stories/LookupStories.tsx From 716a046e8daff587d077090525bc5176914daefb Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Tue, 20 Aug 2019 00:33:39 +0900 Subject: [PATCH 4/8] #289 Lookup: Fix type errors of story --- src/scripts/Lookup.tsx | 16 +++---- stories/LookupStories.tsx | 88 ++++++++++++++++++++++++--------------- 2 files changed, 64 insertions(+), 40 deletions(-) diff --git a/src/scripts/Lookup.tsx b/src/scripts/Lookup.tsx index c401adcc8..851368e54 100644 --- a/src/scripts/Lookup.tsx +++ b/src/scripts/Lookup.tsx @@ -14,11 +14,12 @@ import { uuid, isElInChildren, registerStyle } from './util'; * */ export type LookupEntry = { - category: IconCategory; + scope?: string; + category?: IconCategory; icon: string; label: string; value: string; - meta: string; + meta?: string; }; export type LookupSelectionProps = { @@ -87,7 +88,7 @@ export class LookupSelection extends Component { } } -type LookupScope = { +export type LookupScope = { label: string; value: string; icon: string; @@ -356,7 +357,7 @@ export type LookupCandidateListProps = { data?: LookupEntry[]; focus?: boolean; loading?: boolean; - filter?: (entry: LookupEntry) => LookupEntry; + filter?: (entry: LookupEntry) => boolean; listRef?: (node: HTMLDivElement) => void; onSelect?: (entry: LookupEntry | null) => void; onBlur?: (e: React.FocusEvent) => void; @@ -541,13 +542,15 @@ export type LookupProps = { id?: string; className?: string; label?: string; + disabled?: boolean; required?: boolean; error?: FormElementProps['error']; + iconAlign?: 'left' | 'right'; value?: string; defaultValue?: string; - selected?: LookupEntry; + selected?: LookupEntry | null; defaultSelected?: LookupEntry; opened?: boolean; @@ -562,13 +565,12 @@ export type LookupProps = { entry: LookupEntry, searchText?: string, targetScope?: string - ) => LookupEntry; + ) => boolean; listHeader?: JSX.Element; listFooter?: JSX.Element; scopes?: LookupScope[]; targetScope?: string; defaultTargetScope?: string; - iconAlign?: 'left' | 'right'; totalCols?: number; cols?: number; diff --git a/stories/LookupStories.tsx b/stories/LookupStories.tsx index 92c3d47aa..4c073fdce 100644 --- a/stories/LookupStories.tsx +++ b/stories/LookupStories.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { PropTypes } from 'prop-types'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { text, boolean, object } from '@storybook/addon-knobs'; +import { LookupEntry, LookupScope } from '../src/scripts/Lookup'; import { Button, Lookup } from '../src/scripts'; import COMPANIES from './data/COMPANIES'; import OPPORTUNITIES from './data/OPPORTUNITIES'; @@ -13,35 +13,35 @@ import SCOPES from './data/SCOPES'; /** * example data set used for lookup datasource */ -const COMPANY_DATA = COMPANIES.map((label, i) => ({ +const COMPANY_DATA: LookupEntry[] = COMPANIES.map((label, i) => ({ icon: 'standard:account', label, value: `10000${i}`, meta: '(888)000-0000 / 1234 XXX Ave, BBB City, CA, 90210 USA', scope: 'Account', })); -const OPP_DATA = COMPANIES.map((label, i) => ({ +const OPP_DATA: LookupEntry[] = COMPANIES.map((label, i) => ({ icon: 'standard:opportunity', label: `${label} - ${OPPORTUNITIES[i % OPPORTUNITIES.length]}`, value: `20000${i}`, scope: 'Opportunity', })); -const CAMPAIGN_DATA = CAMPAIGNS.map((label, i) => ({ +const CAMPAIGN_DATA: LookupEntry[] = CAMPAIGNS.map((label, i) => ({ icon: 'standard:campaign', label, value: `30000${i}`, scope: 'Campaign', })); -const CASE_DATA = CASES.map((label, i) => ({ +const CASE_DATA: LookupEntry[] = CASES.map((label, i) => ({ icon: 'standard:case', label, value: `40000${i}`, scope: 'Case', })); -const LOOKUP_SCOPES = SCOPES.map((label) => ({ +const LOOKUP_SCOPES: LookupEntry[] = SCOPES.map((label) => ({ label, value: label, icon: `standard:${label.toLowerCase()}`, @@ -57,7 +57,11 @@ const LOOKUP_DATASET = [ /** * Async function to load datasets */ -function queryData(searchText, targetScope, callback) { +function queryData( + searchText: string, + targetScope: string, + callback: (data: LookupEntry[]) => void +) { setTimeout(() => { const data = LOOKUP_DATASET.filter( (entry) => @@ -68,22 +72,36 @@ function queryData(searchText, targetScope, callback) { }, 1000); } +type LookupControlledProps = { + label?: string; + scopes?: LookupScope[]; + targetScope?: string; + onScopeMenuClick?: (...args: any[]) => void; + onScopeChange?: (targetScope: string) => void; + onSearchTextChange?: (searchText: string) => void; + onLookupRequest?: (searchText?: string) => any; + onSelect?: (selected: LookupEntry) => void; + onComplete?: (...args: any[]) => void; +}; + +type LookupControlledState = { + data: LookupEntry[]; + searchText: string; + selected: LookupEntry | null; + loading: boolean; + opened: boolean; + scopes?: LookupScope[]; + targetScope?: string; +}; + /** * state wrapper class for showing controlled behavior */ -class LookupControlled extends React.Component { - static propTypes = { - scopes: PropTypes.arrayOf(PropTypes.object), - targetScope: PropTypes.string, - onScopeMenuClick: PropTypes.func, - onScopeChange: PropTypes.func, - onSearchTextChange: PropTypes.func, - onLookupRequest: PropTypes.func, - onSelect: PropTypes.func, - onComplete: PropTypes.func, - }; - - constructor(props) { +class LookupControlled extends React.Component< + LookupControlledProps, + LookupControlledState +> { + constructor(props: Readonly) { super(props); this.state = { data: [], @@ -96,28 +114,28 @@ class LookupControlled extends React.Component { }; } - onScopeMenuClick = (...args) => { + onScopeMenuClick = (...args: any[]) => { if (this.props.onScopeMenuClick) { this.props.onScopeMenuClick(...args); } this.setState({ opened: false }); }; - onScopeChange = (targetScope) => { + onScopeChange = (targetScope: string) => { if (this.props.onScopeChange) { this.props.onScopeChange(targetScope); } this.setState({ targetScope }); }; - onSearchTextChange = (searchText) => { + onSearchTextChange = (searchText: string) => { if (this.props.onSearchTextChange) { this.props.onSearchTextChange(searchText); } this.setState({ searchText }); }; - onLookupRequest = (searchText) => { + onLookupRequest = (searchText: string | undefined) => { if (this.props.onLookupRequest) { this.props.onLookupRequest(searchText); } @@ -127,15 +145,17 @@ class LookupControlled extends React.Component { }); }; - onSelect = (selected) => { + onSelect = (selected: LookupEntry) => { if (this.props.onSelect) { this.props.onSelect(selected); } this.setState({ selected }); }; - onComplete = (...args) => { - this.props.onComplete(...args); + onComplete = (...args: any[]) => { + if (this.props.onComplete) { + this.props.onComplete(...args); + } this.setState({ opened: false }); }; @@ -170,13 +190,13 @@ storiesOf('Lookup', module) () => ( + searchText !== undefined && entry.label.toUpperCase().indexOf(searchText.toUpperCase()) === 0 } onSearchTextChange={action('searchTextChange')} @@ -411,6 +432,7 @@ storiesOf('Lookup', module) data={LOOKUP_DATASET} lookupFilter={(entry, searchText, scope) => entry.scope === scope && + searchText !== undefined && entry.label.toUpperCase().indexOf(searchText.toUpperCase()) === 0 } onScopeMenuClick={action('scopeMenuClick')} From c45d204f104f7d51226692033e4ac031394a438a Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Tue, 20 Aug 2019 00:40:27 +0900 Subject: [PATCH 5/8] #289 Lookup: Quit default export --- src/scripts/Lookup.tsx | 2 +- src/scripts/index.js | 3 +-- stories/LookupStories.tsx | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/scripts/Lookup.tsx b/src/scripts/Lookup.tsx index 851368e54..f858d275a 100644 --- a/src/scripts/Lookup.tsx +++ b/src/scripts/Lookup.tsx @@ -594,7 +594,7 @@ export type LookupState = { /** * */ -export default class Lookup extends Component { +export class Lookup extends Component { static isFormElement = true; private node: HTMLDivElement | null = null; diff --git a/src/scripts/index.js b/src/scripts/index.js index 30ce6e6dc..f44a356f9 100644 --- a/src/scripts/index.js +++ b/src/scripts/index.js @@ -9,7 +9,6 @@ import Checkbox from './Checkbox'; import CheckboxGroup from './CheckboxGroup'; import Select, { Option } from './Select'; import DateInput from './DateInput'; -import Lookup from './Lookup'; import FieldSet from './FieldSet'; import Grid, { Row, Col } from './Grid'; import Notification, { Alert, Toast } from './Notification'; @@ -49,7 +48,6 @@ export { Select, Option, DateInput, - Lookup, FieldSet, Grid, Row, @@ -91,6 +89,7 @@ export * from './Form'; export * from './FormElement'; export * from './Input'; export * from './Picklist'; +export * from './Lookup'; export * from './Pill'; export * from './Spinner'; export * from './Text'; diff --git a/stories/LookupStories.tsx b/stories/LookupStories.tsx index 4c073fdce..4ce75f1dd 100644 --- a/stories/LookupStories.tsx +++ b/stories/LookupStories.tsx @@ -2,8 +2,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { text, boolean, object } from '@storybook/addon-knobs'; -import { LookupEntry, LookupScope } from '../src/scripts/Lookup'; -import { Button, Lookup } from '../src/scripts'; +import { Button, Lookup, LookupEntry, LookupScope } from '../src/scripts'; import COMPANIES from './data/COMPANIES'; import OPPORTUNITIES from './data/OPPORTUNITIES'; import CAMPAIGNS from './data/CAMPAIGNS'; From 1873757bdfbb94f061f97f0d781e59254859969d Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Fri, 13 Sep 2019 23:08:47 +0900 Subject: [PATCH 6/8] #289 Pill: Add HTMLAttributes to props --- src/scripts/Pill.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/Pill.tsx b/src/scripts/Pill.tsx index d1e5d73c8..a04722fe8 100644 --- a/src/scripts/Pill.tsx +++ b/src/scripts/Pill.tsx @@ -1,4 +1,4 @@ -import React, { Component, ReactHTML } from 'react'; +import React, { Component, ReactHTML, HTMLAttributes } from 'react'; import classnames from 'classnames'; import { Icon, IconCategory } from './Icon'; @@ -17,7 +17,7 @@ export type PillProps = { pillRef?: (node: HTMLElement) => void; onClick?: (e: React.MouseEvent) => void; onRemove?: (e: any) => void; -}; +} & HTMLAttributes; export class Pill extends Component { onPillClick(e: React.MouseEvent) { From ef66910ce9b14349945b23c1995476c8ef250633 Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Fri, 13 Sep 2019 23:09:10 +0900 Subject: [PATCH 7/8] #289 Lookup: Don't use private field for element --- src/scripts/Lookup.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/scripts/Lookup.tsx b/src/scripts/Lookup.tsx index f858d275a..77a584dd9 100644 --- a/src/scripts/Lookup.tsx +++ b/src/scripts/Lookup.tsx @@ -34,7 +34,7 @@ export type LookupSelectionProps = { * */ export class LookupSelection extends Component { - private pill: HTMLElement | null = null; + pill: HTMLElement | null = null; onKeyDown(e: any) { if (e.keyCode === 8 || e.keyCode === 46) { @@ -118,9 +118,9 @@ export type LookupSearchProps = { * */ export class LookupSearch extends Component { - private input: HTMLInputElement | null = null; + input: HTMLInputElement | null = null; - private node: HTMLDivElement | null = null; + node: HTMLDivElement | null = null; constructor(props: Readonly) { super(props); @@ -369,7 +369,7 @@ export type LookupCandidateListProps = { * */ class LookupCandidateList extends Component { - private node: HTMLDivElement | null = null; + node: HTMLDivElement | null = null; componentDidMount() { if (this.props.focus) { @@ -597,11 +597,11 @@ export type LookupState = { export class Lookup extends Component { static isFormElement = true; - private node: HTMLDivElement | null = null; + node: HTMLDivElement | null = null; - private selection: HTMLDivElement | null = null; + selection: HTMLDivElement | null = null; - private candidateList: HTMLDivElement | null = null; + candidateList: HTMLDivElement | null = null; // eslint-disable-next-line react/sort-comp private search: any; From dbbcbf98f0ffc82368c45d4161d32a5083e338b7 Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Sat, 14 Sep 2019 12:55:44 +0900 Subject: [PATCH 8/8] #289 Lookup: Update storyshots --- test/storyshots/__snapshots__/storyshots.test.js.snap | 1 + 1 file changed, 1 insertion(+) diff --git a/test/storyshots/__snapshots__/storyshots.test.js.snap b/test/storyshots/__snapshots__/storyshots.test.js.snap index d0064bbb9..f366f70e7 100644 --- a/test/storyshots/__snapshots__/storyshots.test.js.snap +++ b/test/storyshots/__snapshots__/storyshots.test.js.snap @@ -29735,6 +29735,7 @@ exports[`Storyshots Lookup Controlled with knobs 1`] = ` >