From 76ac3f43faccc8fd8bca575a68ceeb3a20df9ad9 Mon Sep 17 00:00:00 2001 From: hamed-musallam <35760236+hamed-musallam@users.noreply.github.com> Date: Mon, 3 Jun 2024 10:24:24 +0200 Subject: [PATCH] feat: improve useSelect hook item render (#732) * feat: improve useSelect hook to support custom item rendering * chore(storybook): create a sample for custom select item * refactor: useSelect interface --- src/components/hooks/useSelect.tsx | 21 +++++--- stories/components/select.stories.tsx | 74 ++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/src/components/hooks/useSelect.tsx b/src/components/hooks/useSelect.tsx index 6df83fef..fa4087e1 100644 --- a/src/components/hooks/useSelect.tsx +++ b/src/components/hooks/useSelect.tsx @@ -1,6 +1,6 @@ import { MenuItem } from '@blueprintjs/core'; import { ItemRenderer } from '@blueprintjs/select'; -import { useState } from 'react'; +import { ReactNode, useState } from 'react'; type FilterType = Pick< SourceType, @@ -9,14 +9,17 @@ type FilterType = Pick< }[keyof SourceType] >; -interface BaseOptions { - itemTextKey: keyof FilterType; +interface ItemOptions { + renderItem?: (item: T) => ReactNode; defaultSelectedItem?: T; } -interface RenderOptions { +interface BaseOptions extends ItemOptions { + itemTextKey: keyof FilterType; +} + +interface RenderOptions extends ItemOptions { getItemText: (item: T) => string; - defaultSelectedItem?: T; } type SelectOptions = BaseOptions | RenderOptions; @@ -91,16 +94,18 @@ function getItemRenderer(value: T, options: SelectOptions) { { handleClick, handleFocus, modifiers, index }, ) => { const label = getLabel(item, options); + const { renderItem } = options; + const { active, disabled } = modifiers; return ( ); }; diff --git a/stories/components/select.stories.tsx b/stories/components/select.stories.tsx index 0513d87c..7232b4f5 100644 --- a/stories/components/select.stories.tsx +++ b/stories/components/select.stories.tsx @@ -6,7 +6,14 @@ import { MenuItem, } from '@blueprintjs/core'; import { ItemListRenderer, Select } from '@blueprintjs/select'; -import { Dispatch, Fragment, SetStateAction, useState } from 'react'; +import styled from '@emotion/styled'; +import { + CSSProperties, + Dispatch, + Fragment, + SetStateAction, + useState, +} from 'react'; import { Button, useOnOff, useSelect } from '../../src/components'; @@ -384,6 +391,71 @@ export function WithCustomStyle() { ); } +const Row = styled.div({ + display: 'flex', + flexDirection: 'row', +}); + +const Tag = styled.div({ + borderRadius: '25px', + minWidth: '25px', + minHeight: '25px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + fontSize: '11px', +}); + +export function WithCustomRenderItem() { + const { value, ...defaultProps } = useSelect<{ + label: string; + color: CSSProperties['color']; + }>({ + itemTextKey: 'label', + renderItem: ({ label, color }) => ( + + + {label.charAt(0)} + + {label} + + fruits + + + ), + }); + return ( + <> + +

Value outside component is {value?.label}.

+ + ); +} + export function FixedValueNoopHandle() { const defaultProps = useSelect<{ label: string }>({ itemTextKey: 'label' }); const value = { label: 'Orange' };