From 2e797b2abd1b919497eb4027494381e07b848181 Mon Sep 17 00:00:00 2001 From: OsamaAbdellateef Date: Thu, 9 Jan 2025 15:38:11 +0200 Subject: [PATCH] Adding on remove function and filter --- .../src/Multiselect/Multiselect.tsx | 86 +++++++++++++++++-- 1 file changed, 81 insertions(+), 5 deletions(-) diff --git a/packages/components/src/Multiselect/Multiselect.tsx b/packages/components/src/Multiselect/Multiselect.tsx index 05d809073a..e3519fd0d9 100644 --- a/packages/components/src/Multiselect/Multiselect.tsx +++ b/packages/components/src/Multiselect/Multiselect.tsx @@ -1,10 +1,17 @@ import { ForwardRefExoticComponent, + Key, ReactNode, RefAttributes, forwardRef, + useCallback, + useId, + useRef, + useState, } from 'react'; import type RAC from 'react-aria-components'; +import { useFilter } from '@react-aria/i18n'; +import { ListData, useListData } from '@react-stately/data'; import { FieldBase, FieldBaseProps } from '../FieldBase'; import { ListBox } from '../ListBox'; @@ -20,9 +27,10 @@ type RemovedProps = | 'isReadOnly' | 'defaultInputValue' | 'inputValue' - | 'onInputChange'; + | 'onInputChange' + | 'items'; -export interface MultiselectProps +export interface MultiselectProps extends Omit, RemovedProps>, Pick< FieldBaseProps<'label'>, @@ -31,6 +39,11 @@ export interface MultiselectProps variant?: string; size?: string; + items: { id: string; name: string }[]; + + // TODO: Remove any 🙂 + selectedItems: ListData; + /** * If `true`, the input is disabled. * @default false @@ -70,6 +83,8 @@ export interface MultiselectProps */ onChange?: RAC.ComboBoxProps['onInputChange']; + onItemCleared?: (key: Key) => void; + /** * ReactNode or function to render the list of items. */ @@ -83,7 +98,7 @@ export interface MultiselectProps interface MultiselectComponent extends ForwardRefExoticComponent< - MultiselectProps & RefAttributes + MultiselectProps & RefAttributes > { /** * Options for the Combobox. @@ -99,7 +114,7 @@ interface MultiselectComponent // Component // --------------- -export const Multiselect = forwardRef( +export const Multiselect = forwardRef>( ( { variant, @@ -111,11 +126,72 @@ export const Multiselect = forwardRef( defaultValue, value, onChange, + onItemCleared, children, + selectedItems, + items, ...rest }, ref ) => { - return
Hello there
; + const tagGroupIdentifier = useId(); + const triggerRef = useRef(null); + const [width, setWidth] = useState(0); + + const { contains } = useFilter({ + sensitivity: 'base', + }); + + const selectedKeys = selectedItems.items.map(item => item.id); + + const filter = useCallback( + (item: { id: string; name: string }, filterText: string) => { + return ( + !selectedKeys.includes(item.id) && contains(item.name, filterText) + ); + }, + [contains, selectedKeys] + ); + + const accessibleList = useListData({ + initialItems: items, + filter, + }); + + const [fieldState, setFieldState] = useState<{ + selectedKey: Key | null; + inputValue: string; + }>({ + selectedKey: null, + inputValue: '', + }); + + const onRemove = useCallback( + (keys: Set) => { + // TODO: clarify why this is an array + const key = keys.values().next().value; + if (key) { + selectedItems.remove(key); + setFieldState({ + inputValue: '', + selectedKey: null, + }); + onItemCleared?.(key); + } + }, + [selectedItems, onItemCleared] + ); + + return ( + // container +
wfe
+ ); } ); + +/** + * -container + * --tag group (we use their tag group giving it the same styles like ours) + * --fieldbase + * ---input + */