Skip to content

Commit

Permalink
[CPT-1478] Add enableResetSearch prop to Select and QB (#4075)
Browse files Browse the repository at this point in the history
* [CPT-1478] Add enableResetSearch prop to Select and QB

* [CPT-1478] Address review

* Create seperate changesets for packages

* Update  multiselect input field type

---------

Co-authored-by: Rasit Ozcan <[email protected]>
  • Loading branch information
angelinastavniiciuc and rasitozcan authored Jan 8, 2024
1 parent 6ef3992 commit 2d0c9d4
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/rare-jokes-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@toptal/picasso': minor
---

- add `enableResetSearch` prop to `Select` component to render reset icon which clears search input
5 changes: 5 additions & 0 deletions .changeset/spicy-tips-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@toptal/picasso-query-builder': minor
---

- add search input clearing functionality for `select` and `multiselect` filter types through filter configuration with `enableResetSearch` property.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const MultiSelect = ({
value={values}
status={hasError ? 'error' : undefined}
data-testid={valueEditorTestId}
enableResetSearch={fieldData?.enableResetSearch}
/>
</Container>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ const fields: Field[] = [
name: 'alsoPlays',
label: 'Also plays',
valueEditorType: 'multiselect',
enableResetSearch: true,
values: musicalInstruments,
defaultValue: 'More cowbell',
},
Expand Down
17 changes: 15 additions & 2 deletions packages/picasso-query-builder/src/types/query-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export type RangeValue = {
interface BasicField
extends Omit<QueryBuilderField, 'inputType' | 'valueEditorType'> {
inputType?: 'text' | 'number' | null
valueEditorType?: 'text' | 'number' | 'select' | 'multiselect' | null
valueEditorType?: 'text' | 'number' | 'select' | null
hideOperator?: boolean
}
interface RangeField
Expand All @@ -34,6 +34,14 @@ interface BooleanField
extends Omit<QueryBuilderField, 'inputType' | 'valueEditorType' | 'values'> {
valueEditorType?: 'boolean'
}
interface MultiSelectField
extends Omit<QueryBuilderField, 'inputType' | 'valueEditorType'> {
valueEditorType?: 'multiselect'
/**
* Allow search input reset
*/
enableResetSearch?: boolean
}

interface AutoCompleteField
extends Omit<QueryBuilderField, 'inputType' | 'valueEditorType'> {
Expand All @@ -54,7 +62,12 @@ interface AutoCompleteField

export type BaseValueEditorProps = Omit<ValueEditorProps, 'schema'>
export type BaseVersatileSelectorProps = Omit<VersatileSelectorProps, 'schema'>
export type Field = BasicField | RangeField | AutoCompleteField | BooleanField
export type Field =
| BasicField
| RangeField
| AutoCompleteField
| BooleanField
| MultiSelectField
export type QueryBuilderErrors = {
[key: string]: ValidationResult | true
}
Expand Down
2 changes: 2 additions & 0 deletions packages/picasso/src/NonNativeSelect/NonNativeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const NonNativeSelect = documentable(
enableReset,
popperContainer,
enableAutofill,
enableResetSearch,
autoComplete,
searchPlaceholder,
searchThreshold = DEFAULT_SEARCH_THRESHOLD,
Expand Down Expand Up @@ -135,6 +136,7 @@ export const NonNativeSelect = documentable(
</InputAdornment>
}
placeholder={searchPlaceholder}
enableReset={enableResetSearch}
size={size}
value={filterOptionsValue}
testIds={testIds}
Expand Down
28 changes: 28 additions & 0 deletions packages/picasso/src/NonNativeSelect/test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable max-statements */
/* eslint-disable max-lines */
import React from 'react'
import type { PicassoConfig } from '@toptal/picasso/test-utils'
Expand Down Expand Up @@ -169,6 +170,33 @@ describe('NonNativeSelect', () => {
expect(queryByTestId('loader')).toBeInTheDocument()
})

it('renders reset icon when `enableResetSearch` is set to true', () => {
const placeholder = 'Choose an option...'
const searchPlaceholder = 'Search for an option'

const { getByPlaceholderText, queryByTestId } = renderSelect({
options: OPTIONS,
placeholder,
searchPlaceholder,
searchThreshold: -1,
enableResetSearch: true,
testIds: {
resetButton: 'reset-search-input',
},
})

const selectInput = getByPlaceholderText(placeholder)

fireEvent.click(selectInput)

const searchInput = getByPlaceholderText(searchPlaceholder)

fireEvent.focus(searchInput)
fireEvent.change(searchInput, { target: { value: '3' } })

expect(queryByTestId('reset-search-input')).toBeInTheDocument()
})

it('filters options based on entered value to the input field', () => {
const placeholder = 'Choose an option...'
const searchPlaceholder = 'Search for an option'
Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Select.defaultProps = {
searchPlaceholder: 'Search',
native: false,
status: 'default',
enableResetSearch: false,
}

export default Select
17 changes: 16 additions & 1 deletion packages/picasso/src/Select/story/SearchBehavior.example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const SelectSearchBehaviourExample = () => {
/>
</Form.Field>
</Container>
<Container>
<Container right={SPACING_4}>
<Form.Field>
<Form.Label>Search threshold</Form.Label>
<NumberInput
Expand All @@ -48,6 +48,21 @@ const SelectSearchBehaviourExample = () => {
/>
</Form.Field>
</Container>
<Container>
<Form.Field>
<Form.Label>Search with input reset</Form.Label>
<Select
onChange={handleChange}
value={value}
options={OPTIONS}
placeholder='Choose an option...'
width='auto'
enableResetSearch
searchThreshold={threshold}
data-testid='select'
/>
</Form.Field>
</Container>
</Container>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './use-search-reset-handler'
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { renderHook } from '@testing-library/react'

import { getUseSelectPropsMock } from '../mocks'
import useSearchResetHandler from './use-search-reset-handler'

describe('useSearchResetHandler', () => {
it('handles reset', () => {
const props = getUseSelectPropsMock()
const { result } = renderHook(() => useSearchResetHandler(props))

result.current()

expect(props.selectState.setFilterOptionsValue).toHaveBeenCalledTimes(1)
expect(props.selectState.setFilterOptionsValue).toHaveBeenCalledWith('')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { ValueType, UseSelectProps } from '../../../types'

const useSearchResetHandler =
<T extends ValueType, M extends boolean = false>({
selectState: { setFilterOptionsValue },
}: UseSelectProps<T, M>) =>
() =>
setFilterOptionsValue('')

export default useSearchResetHandler
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable max-statements */
import type {
Option,
ItemProps,
Expand All @@ -20,6 +21,7 @@ import useSearchChangeHandler from './use-search-change-handler'
import useItemOnMouseDownHandler from './use-item-on-mouse-down-handler'
import useItemOnMouseEnter from './use-item-on-mouse-enter-handler'
import useItemOnClick from './use-item-on-click-handler'
import useSearchResetHandler from './use-search-reset-handler'

const useSelectProps = <T extends ValueType, M extends boolean = false>(
props: UseSelectProps<T, M>
Expand All @@ -39,6 +41,7 @@ const useSelectProps = <T extends ValueType, M extends boolean = false>(
...props,
handleSelect,
})
const handleSearchReset = useSearchResetHandler(props)
const handleSearchChange = useSearchChangeHandler(props)
const handleItemOnMouseDown = useItemOnMouseDownHandler()
const handleItemOnMouseEnter = useItemOnMouseEnter(props)
Expand Down Expand Up @@ -77,6 +80,7 @@ const useSelectProps = <T extends ValueType, M extends boolean = false>(
onChange: handleSearchChange,
onKeyDown: handleSearchKeyDown,
onBlur: handleSearchBlur,
onResetClick: handleSearchReset,
})

return {
Expand Down
2 changes: 2 additions & 0 deletions packages/picasso/src/SelectBase/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ export interface SelectProps<
size?: SizeType<'small' | 'medium' | 'large'>
/** Whether to render reset icon which clears selected value */
enableReset?: boolean
/** Whether to render reset icon which clears search input value */
enableResetSearch?: boolean
popperContainer?: HTMLElement
/** Defines the minimum options number to show the search
* @default 10
Expand Down

0 comments on commit 2d0c9d4

Please sign in to comment.