Skip to content

Commit

Permalink
chore: add renderPopup
Browse files Browse the repository at this point in the history
  • Loading branch information
GermanVor committed Feb 6, 2024
1 parent 1d2bcb8 commit b2b61ef
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 39 deletions.
91 changes: 57 additions & 34 deletions src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {DEFAULT_VIRTUALIZATION_THRESHOLD, selectBlock} from './constants';
import {useQuickSearch} from './hooks';
import {initialState, reducer} from './store';
import {Option, OptionGroup} from './tech-components';
import type {SelectProps} from './types';
import type {SelectProps, SelectRenderPopup} from './types';
import type {SelectFilterRef} from './types-misc';
import {
activateFirstClickableItem,
Expand All @@ -34,6 +34,15 @@ type SelectComponent = (<T = any>(
p: SelectProps<T> & {ref?: React.Ref<HTMLButtonElement>},
) => React.ReactElement) & {Option: typeof Option} & {OptionGroup: typeof OptionGroup};

export const DEFAULT_RENDER_POPUP: SelectRenderPopup = ({renderFilter, renderList}) => {
return (
<React.Fragment>
{renderFilter()}
{renderList()}
</React.Fragment>
);
};

export const Select = React.forwardRef<HTMLButtonElement, SelectProps>(function Select<T = any>(
props: SelectProps<T>,
ref: React.Ref<HTMLButtonElement>,
Expand All @@ -48,6 +57,7 @@ export const Select = React.forwardRef<HTMLButtonElement, SelectProps>(function
renderOptionGroup,
renderSelectedOption,
renderEmptyOptions,
renderPopup = DEFAULT_RENDER_POPUP,
getOptionHeight,
getOptionGroupHeight,
filterOption,
Expand Down Expand Up @@ -245,6 +255,51 @@ export const Select = React.forwardRef<HTMLButtonElement, SelectProps>(function
),
});

const _renderFilter = () => {
if (filterable) {
return (
<SelectFilter
ref={filterRef}
size={size}
value={filter}
placeholder={filterPlaceholder}
onChange={handleFilterChange}
onKeyDown={handleFilterKeyDown}
renderFilter={renderFilter}
/>
);
}

return null;
};

const _renderList = () => {
if (filteredFlattenOptions.length || props.loading) {
return (
<SelectList
ref={listRef}
size={size}
value={value}
mobile={mobile}
flattenOptions={filteredFlattenOptions}
multiple={multiple}
virtualized={virtualized}
onOptionClick={handleOptionClick}
renderOption={renderOption}
renderOptionGroup={renderOptionGroup}
getOptionHeight={getOptionHeight}
getOptionGroupHeight={getOptionGroupHeight}
loading={props.loading}
onLoadMore={props.onLoadMore}
selectId={`select-${selectId}`}
onChangeActive={setActiveIndex}
/>
);
}

return <EmptyOptions filter={filter} renderEmptyOptions={renderEmptyOptions} />;
};

return (
<div
ref={controlWrapRef}
Expand Down Expand Up @@ -291,39 +346,7 @@ export const Select = React.forwardRef<HTMLButtonElement, SelectProps>(function
id={`select-popup-${selectId}`}
placement={popupPlacement}
>
{filterable && (
<SelectFilter
ref={filterRef}
size={size}
value={filter}
placeholder={filterPlaceholder}
onChange={handleFilterChange}
onKeyDown={handleFilterKeyDown}
renderFilter={renderFilter}
/>
)}
{filteredFlattenOptions.length || props.loading ? (
<SelectList
ref={listRef}
size={size}
value={value}
mobile={mobile}
flattenOptions={filteredFlattenOptions}
multiple={multiple}
virtualized={virtualized}
onOptionClick={handleOptionClick}
renderOption={renderOption}
renderOptionGroup={renderOptionGroup}
getOptionHeight={getOptionHeight}
getOptionGroupHeight={getOptionGroupHeight}
loading={props.loading}
onLoadMore={props.onLoadMore}
selectId={`select-${selectId}`}
onChangeActive={setActiveIndex}
/>
) : (
<EmptyOptions filter={filter} renderEmptyOptions={renderEmptyOptions} />
)}
{renderPopup({renderFilter: _renderFilter, renderList: _renderList})}
</SelectPopup>

<OuterAdditionalContent
Expand Down
30 changes: 25 additions & 5 deletions src/components/Select/__stories__/SelectShowcase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,7 @@ const ExampleItem = (props: {
)}
</h3>
{mode === Mode.VIEW ? (
<Select
{...selectProps}
value={value}
onUpdate={(nextValue) => setValue(nextValue)}
>
<Select {...selectProps} value={value} onUpdate={setValue}>
{children}
</Select>
) : (
Expand Down Expand Up @@ -414,6 +410,30 @@ export const SelectShowcase = (props: SelectProps) => {
<Select.Option value="val4" content="Value4" />
</ExampleItem>
</div>

<ExampleItem
title="Select with custom popup"
selectProps={{
...props,
filterable: true,
renderPopup: ({renderFilter, renderList}) => {
return (
<React.Fragment>
<div>{'---- Before Filter ----'}</div>
{renderFilter()}
<div>{'---- After Filter, Before List ----'}</div>
{renderList()}
<div>{'---- After List ----'}</div>
</React.Fragment>
);
},
}}
>
<Select.Option value="val1" content="Value1" />
<Select.Option value="val2" content="Value2" />
<Select.Option value="val3" content="Value3" />
<Select.Option value="val4" content="Value4" />
</ExampleItem>
</div>
);
};
6 changes: 6 additions & 0 deletions src/components/Select/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export type SelectRenderOptionGroup<T> = (
options: SelectRenderOptionViewParams,
) => React.ReactElement;

export type SelectRenderPopup = (popupItems: {
renderFilter: () => React.JSX.Element | null;
renderList: () => React.JSX.Element;
}) => React.ReactElement;

export type SelectSize = InputControlSize;

export type SelectProps<T = any> = QAProps &
Expand All @@ -63,6 +68,7 @@ export type SelectProps<T = any> = QAProps &
renderOptionGroup?: SelectRenderOptionGroup<T>;
renderSelectedOption?: (option: SelectOption<T>, index: number) => React.ReactElement;
renderEmptyOptions?: ({filter}: {filter: string}) => React.ReactElement;
renderPopup?: SelectRenderPopup;
getOptionHeight?: (option: SelectOption<T>, index: number) => number;
getOptionGroupHeight?: (option: SelectOptionGroup<T>, index: number) => number;
filterOption?: (option: SelectOption<T>, filter: string) => boolean;
Expand Down

0 comments on commit b2b61ef

Please sign in to comment.