From 41c7fa992a9d9b0f59f0c5a071cef20ec7a3348c Mon Sep 17 00:00:00 2001 From: juliajforesti Date: Wed, 23 Feb 2022 13:35:08 -0300 Subject: [PATCH] Fix Select filter --- .../fuselage/src/components/Select/Select.tsx | 42 ++++++--- .../components/Select/SelectAnchorParams.ts | 17 ++++ .../src/components/Select/SelectFiltered.tsx | 92 ++++++------------- .../Select/SelectFilteredAnchor.tsx | 52 +++++++++++ 4 files changed, 128 insertions(+), 75 deletions(-) create mode 100644 packages/fuselage/src/components/Select/SelectAnchorParams.ts create mode 100644 packages/fuselage/src/components/Select/SelectFilteredAnchor.tsx diff --git a/packages/fuselage/src/components/Select/Select.tsx b/packages/fuselage/src/components/Select/Select.tsx index 0ea5aa1b61..006ad91656 100644 --- a/packages/fuselage/src/components/Select/Select.tsx +++ b/packages/fuselage/src/components/Select/Select.tsx @@ -3,9 +3,16 @@ import { useMutableCallback, useResizeObserver, } from '@rocket.chat/fuselage-hooks'; -import type { ComponentProps, DependencyList, Ref, ElementType } from 'react'; +import type { + ComponentProps, + DependencyList, + Ref, + ElementType, + ReactNode, +} from 'react'; import React, { useState, useRef, useEffect, forwardRef, useMemo } from 'react'; +import { isForwardRefType } from '../../helpers/isForwardRefType'; import AnimatedVisibility from '../AnimatedVisibility'; import { Box } from '../Box'; import { Icon } from '../Icon'; @@ -14,6 +21,7 @@ import type { OptionType } from '../Options'; import { Options, useCursor } from '../Options'; import PositionAnimated from '../PositionAnimated'; import SelectAddon from './SelectAddon'; +import type { SelectAnchorParams } from './SelectAnchorParams'; import SelectFocus from './SelectFocus'; export type SelectOption = readonly [ @@ -116,6 +124,18 @@ export const Select = forwardRef( const innerRef = useRef(null); const anchorRef = useMergedRefs(ref, innerRef); + const renderAnchor = (params: SelectAnchorParams) => { + if (isForwardRefType(Anchor)) { + return ; + } + + if (typeof Anchor === 'function') { + return (Anchor as (params: SelectAnchorParams) => ReactNode)(params); + } + + return null; + }; + const { ref: containerRef, borderBoxSize } = useResizeObserver(); useDidUpdate(reset, [filter, internalValue]); @@ -171,17 +191,15 @@ export const Select = forwardRef( {visibleText} ))} - + {renderAnchor({ + ref: anchorRef, + children: !value ? option || placeholder : null, + disabled: disabled ?? false, + onClick: show, + onBlur: hide, + onKeyDown: handleKeyDown, + onKeyUp: handleKeyUp, + })} ; + children: ReactNode; + disabled: boolean; + onClick: MouseEventHandler; + onBlur: FocusEventHandler; + onKeyUp: KeyboardEventHandler; + onKeyDown: KeyboardEventHandler; +}; diff --git a/packages/fuselage/src/components/Select/SelectFiltered.tsx b/packages/fuselage/src/components/Select/SelectFiltered.tsx index 4d8d8aee4d..aef7d3f90b 100644 --- a/packages/fuselage/src/components/Select/SelectFiltered.tsx +++ b/packages/fuselage/src/components/Select/SelectFiltered.tsx @@ -1,16 +1,10 @@ -import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import type { - ComponentProps, - Dispatch, - FormEvent, - Ref, - SetStateAction, -} from 'react'; -import React, { forwardRef, useCallback, useState } from 'react'; +import type { ComponentProps, Dispatch, SetStateAction } from 'react'; +import React, { useState } from 'react'; import { Select } from '.'; import type { Icon } from '..'; -import { InputBox } from '../InputBox'; +import type { SelectAnchorParams } from './SelectAnchorParams'; +import SelectFilteredAnchor from './SelectFilteredAnchor'; export type SelectFilteredProps = ComponentProps & { filter?: string; @@ -18,57 +12,29 @@ export type SelectFilteredProps = ComponentProps & { addonIcon?: ComponentProps['name']; }; -export const SelectFiltered = forwardRef( - ( - { - options, - placeholder, - filter: propFilter, - setFilter: propSetFilter, - ...props - }: SelectFilteredProps, - ref: Ref - ) => { - const [filter, setFilter] = useState(''); - const anchor = useCallback( - forwardRef( - ( - { - children: _children, - filter, - ...props - }: ComponentProps, - ref: Ref - ) => ( - ) => - propSetFilter - ? propSetFilter(e.currentTarget.value) - : setFilter(e.currentTarget.value) - )} - {...props} - rcx-input-box--undecorated - /> - ) - ), - [] - ); +export const SelectFiltered = ({ + options, + placeholder, + filter: propFilter, + setFilter: propSetFilter, + ...props +}: SelectFilteredProps) => { + const [filter, setFilter] = useState(''); - return ( - ( + + )} + /> + ); +}; diff --git a/packages/fuselage/src/components/Select/SelectFilteredAnchor.tsx b/packages/fuselage/src/components/Select/SelectFilteredAnchor.tsx new file mode 100644 index 0000000000..792fb2a20e --- /dev/null +++ b/packages/fuselage/src/components/Select/SelectFilteredAnchor.tsx @@ -0,0 +1,52 @@ +import type { + FocusEventHandler, + FormEvent, + KeyboardEventHandler, + MouseEventHandler, + ReactNode, + Ref, +} from 'react'; +import React, { forwardRef } from 'react'; + +import { InputBox } from '../InputBox'; + +type SelectFilteredAnchorProps = { + children: ReactNode; + disabled: boolean; + filter: string; + onChangeFilter: (filter: string) => void; + placeholder?: string; + onClick: MouseEventHandler; + onBlur: FocusEventHandler; + onKeyUp: KeyboardEventHandler; + onKeyDown: KeyboardEventHandler; +}; + +const SelectFilteredAnchor = forwardRef(function SelectFilteredAnchor( + { + children: _children, + filter, + onChangeFilter, + placeholder, + ...props + }: SelectFilteredAnchorProps, + ref: Ref +) { + return ( + ) => + onChangeFilter(e.currentTarget.value) + } + {...props} + rcx-input-box--undecorated + /> + ); +}); + +export default SelectFilteredAnchor;