From 98a41330dc212dd069ebfb6ab6c4d2c343ae4774 Mon Sep 17 00:00:00 2001 From: glagioia Date: Sat, 16 Nov 2024 15:48:31 -0300 Subject: [PATCH] Adding collapsable prop for multiselect groups --- components/doc/common/apidoc/index.json | 32 +++++++++++ components/doc/multiselect/groupdoc.js | 9 +-- components/lib/multiselect/MultiSelect.js | 3 +- components/lib/multiselect/MultiSelectBase.js | 12 ++++ .../lib/multiselect/MultiSelectPanel.js | 55 +++++++++++++++++-- components/lib/multiselect/multiselect.d.ts | 4 ++ 6 files changed, 105 insertions(+), 10 deletions(-) diff --git a/components/doc/common/apidoc/index.json b/components/doc/common/apidoc/index.json index f0d4a44314..fe40e8f9c6 100644 --- a/components/doc/common/apidoc/index.json +++ b/components/doc/common/apidoc/index.json @@ -3882,6 +3882,14 @@ "default": "", "description": "Template of an option group item." }, + { + "name": "optionGroupCollapsable", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "", + "description": "Option to collapse group items." + }, { "name": "panelClassName", "optional": true, @@ -23421,6 +23429,14 @@ "default": "", "description": "Template of an option group item." }, + { + "name": "optionGroupCollapsable", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "", + "description": "Option to collapse group items." + }, { "name": "optionLabel", "optional": true, @@ -32963,6 +32979,14 @@ "default": "", "description": "Template of an option group item." }, + { + "name": "optionGroupCollapsable", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "", + "description": "Option to collapse group items." + }, { "name": "optionLabel", "optional": true, @@ -36544,6 +36568,14 @@ "default": "", "description": "Template of an option group item." }, + { + "name": "optionGroupCollapsable", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "", + "description": "Option to collapse group items." + }, { "name": "optionLabel", "optional": true, diff --git a/components/doc/multiselect/groupdoc.js b/components/doc/multiselect/groupdoc.js index a1b935f950..d816620879 100644 --- a/components/doc/multiselect/groupdoc.js +++ b/components/doc/multiselect/groupdoc.js @@ -50,7 +50,7 @@ export function GroupDoc(props) { const code = { basic: ` setSelectedCities(e.value)} optionLabel="label" - optionGroupLabel="label" optionGroupChildren="items" optionGroupTemplate={groupedItemTemplate} + optionGroupLabel="label" optionGroupChildren="items" optionGroupTemplate={groupedItemTemplate} optionGroupCollapsable placeholder="Select Cities" display="chip" className="w-full md:w-20rem" /> `, javascript: ` @@ -104,7 +104,7 @@ export default function GroupedDoc() { return (
setSelectedCities(e.value)} optionLabel="label" - optionGroupLabel="label" optionGroupChildren="items" optionGroupTemplate={groupedItemTemplate} + optionGroupLabel="label" optionGroupChildren="items" optionGroupCollapsable optionGroupTemplate={groupedItemTemplate} placeholder="Select Cities" display="chip" className="w-full md:w-20rem" />
); @@ -172,7 +172,7 @@ export default function GroupedDoc() { return (
setSelectedCities(e.value)} optionLabel="label" - optionGroupLabel="label" optionGroupChildren="items" optionGroupTemplate={groupedItemTemplate} + optionGroupLabel="label" optionGroupChildren="items" optionGroupCollapsable optionGroupTemplate={groupedItemTemplate} placeholder="Select Cities" display="chip" className="w-full md:w-20rem" />
); @@ -185,7 +185,7 @@ export default function GroupedDoc() {

Options can be grouped when a nested data structures is provided. To define the label of a group optionGroupLabel property is needed and also optionGroupChildren is required to define the property that refers to the - children of a group. + children of a group. Also you can provide a optionGroupCollapsable property to collapse the groups by default.

@@ -200,6 +200,7 @@ export default function GroupedDoc() { placeholder="Select Cities" display="chip" className="w-full md:w-20rem" + optionGroupCollapsable />
diff --git a/components/lib/multiselect/MultiSelect.js b/components/lib/multiselect/MultiSelect.js index b815d754da..b01c593413 100644 --- a/components/lib/multiselect/MultiSelect.js +++ b/components/lib/multiselect/MultiSelect.js @@ -872,7 +872,6 @@ export const MultiSelect = React.memo( const labelKey = label + '_' + i; const iconProps = mergeProps( { - 'aria-label': localeOption('removeTokenIcon'), className: cx('removeTokenIcon'), onClick: (e) => removeChip(e, val), onKeyDown: (e) => onRemoveTokenIconKeyDown(e, val), @@ -1022,7 +1021,6 @@ export const MultiSelect = React.memo( const clearIconProps = mergeProps( { className: cx('clearIcon'), - 'aria-label': localeOption('clear'), onClick: (e) => updateModel(e, [], []), onKeyDown: (e) => onClearIconKeyDown(e), tabIndex: props.tabIndex || '0' @@ -1199,6 +1197,7 @@ export const MultiSelect = React.memo( isUnstyled={isUnstyled} metaData={metaData} changeFocusedOptionIndex={changeFocusedOptionIndex} + optionGroupCollapsable={props.optionGroupCollapsable} /> {hasTooltip && } diff --git a/components/lib/multiselect/MultiSelectBase.js b/components/lib/multiselect/MultiSelectBase.js index 13aece7cd7..73c215a297 100644 --- a/components/lib/multiselect/MultiSelectBase.js +++ b/components/lib/multiselect/MultiSelectBase.js @@ -190,6 +190,18 @@ const styles = ` .p-fluid .p-multiselect { display: flex; } + .p-multiselect-group-header{ + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.75rem 1.25rem; + cursor: pointer; + } +} + .p-multiselect-group-header:hover{ + background-color: var(--primary-100); + + } } `; diff --git a/components/lib/multiselect/MultiSelectPanel.js b/components/lib/multiselect/MultiSelectPanel.js index 5f5a7b4490..50c0b83e3f 100644 --- a/components/lib/multiselect/MultiSelectPanel.js +++ b/components/lib/multiselect/MultiSelectPanel.js @@ -14,8 +14,15 @@ export const MultiSelectPanel = React.memo( const filterInputRef = React.useRef(null); const mergeProps = useMergeProps(); const context = React.useContext(PrimeReactContext); - const { ptm, cx, sx, isUnstyled } = props; - + const { ptm, cx, sx, isUnstyled, optionGroupCollapsable = false } = props; + const [groupVisibility, setGroupVisibility] = React.useState({}); + + const toggleGroupVisibility = (groupLabel) => { + setGroupVisibility((prev) => ({ + ...prev, + [groupLabel]: !prev[groupLabel] + })); + }; const getPTOptions = (key, options) => { return ptm(key, { hostName: props.hostName, @@ -23,6 +30,19 @@ export const MultiSelectPanel = React.memo( }); }; + React.useEffect(() => { + if (props.optionGroupLabel) { + const initialVisibility = {}; + props.visibleOptions.forEach((option) => { + if (option.group) { + const groupLabel = props.getOptionGroupLabel(option); + initialVisibility[groupLabel] = true; + } + }); + setGroupVisibility(initialVisibility); + } + }, []); + const onEnter = () => { props.onEnter(() => { if (virtualScrollerRef.current) { @@ -189,9 +209,36 @@ export const MultiSelectPanel = React.memo( const createItems = () => { if (ObjectUtils.isNotEmpty(props.visibleOptions)) { - return props.visibleOptions.map(createItem); + return props.visibleOptions.map((option, index) => { + if (option.group && props.optionGroupLabel) { + const groupLabel = props.getOptionGroupLabel(option); + const isVisible = groupVisibility[groupLabel]; + const groupContent = props.optionGroupTemplate ? ObjectUtils.getJSXElement(props.optionGroupTemplate, option, index) : props.getOptionGroupLabel(option); + + const groupHeaderClass = classNames('p-multiselect-group-header'); + + return ( +
+
toggleGroupVisibility(groupLabel)} className={groupHeaderClass} style={{ cursor: 'pointer' }}> + {groupContent} + {optionGroupCollapsable && ( + + )} +
+ {(isVisible || !optionGroupCollapsable) && props.getOptionGroupChildren(option).map((child, childIndex) => createItem(child, `${index}_${childIndex}`))} +
+ ); + } else if (!props.optionGroupLabel) { + return createItem(option, index); + } + return null; + }); } - return props.hasFilter ? createEmptyFilter() : createEmptyContent(); }; diff --git a/components/lib/multiselect/multiselect.d.ts b/components/lib/multiselect/multiselect.d.ts index 3d51df033c..b11ac53ac9 100644 --- a/components/lib/multiselect/multiselect.d.ts +++ b/components/lib/multiselect/multiselect.d.ts @@ -579,6 +579,10 @@ export interface MultiSelectProps extends Omit