From 71ef1a2ad2611556bc856d30e404cdc587badbc8 Mon Sep 17 00:00:00 2001 From: devanshu052000 Date: Wed, 9 Apr 2025 23:41:55 +0530 Subject: [PATCH 01/15] Support for clearing value when selecting an already selected value. --- frontend/src/Editor/Components/DropdownV2/DropdownV2.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/Editor/Components/DropdownV2/DropdownV2.jsx b/frontend/src/Editor/Components/DropdownV2/DropdownV2.jsx index 382ba010ed..a7eb0abb19 100644 --- a/frontend/src/Editor/Components/DropdownV2/DropdownV2.jsx +++ b/frontend/src/Editor/Components/DropdownV2/DropdownV2.jsx @@ -459,7 +459,9 @@ export const DropdownV2 = ({ fireEvent('onSelect'); } if (actionProps.action === 'select-option') { - setInputValue(selectedOption.value); + if (currentValue === selectedOption.value) { + setInputValue(null); + } else setInputValue(selectedOption.value); fireEvent('onSelect'); } setUserInteracted(true); From 713df76ac3805f8a66dee73bf6d189c462ee8d69 Mon Sep 17 00:00:00 2001 From: devanshu052000 Date: Thu, 10 Apr 2025 18:28:49 +0530 Subject: [PATCH 02/15] Fixed interactions in Dropdown --- .../Components/DropdownV2/CustomMenuList.jsx | 10 +++- .../Components/DropdownV2/DropdownV2.jsx | 56 ++++++++++++------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/frontend/src/Editor/Components/DropdownV2/CustomMenuList.jsx b/frontend/src/Editor/Components/DropdownV2/CustomMenuList.jsx index 848de076ae..c606cc7560 100644 --- a/frontend/src/Editor/Components/DropdownV2/CustomMenuList.jsx +++ b/frontend/src/Editor/Components/DropdownV2/CustomMenuList.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { components } from 'react-select'; import SolidIcon from '@/_ui/Icon/SolidIcons'; import Loader from '@/ToolJetUI/Loader/Loader'; @@ -33,6 +33,14 @@ const CustomMenuList = ({ selectProps, ...props }) => { } setIsSelectAllSelected(e.target.checked); }; + + useEffect(() => { + const searchInput = document.querySelector('.dropdown-multiselect-widget-search-box'); + if (searchInput) { + searchInput.focus(); + } + }, []); + return (
state.currentMode); - const isEditor = currentMode === 'edit'; const _height = padding === 'default' ? `${height}px` : `${height + 4}px`; const labelRef = useRef(); @@ -173,12 +170,38 @@ export const DropdownV2 = ({ setExposedVariable('isValid', validationStatus?.isValid); }; - const handleClickInEditor = (e) => { - if (e.target.className.includes('clear-indicator') || isMenuOpen) return; - e.stopPropagation(); - selectRef.current?.onControlMouseDown(e); + const handleClickInsideSelect = () => { + if (isDropdownDisabled || isDropdownLoading) return; + if (isMenuOpen) { + setIsMenuOpen(false); + fireEvent('onBlur'); + } else { + setIsMenuOpen(true); + fireEvent('onFocus'); + } }; + const handleClickOutsideSelect = (event) => { + const menu = document.querySelector(`._tooljet-${componentName}`); + if ( + isMenuOpen && + menu && + dropdownRef.current && + !dropdownRef.current.contains(event.target) && + !menu.contains(event.target) + ) { + setIsMenuOpen(false); + fireEvent('onBlur'); + } + }; + + useEffect(() => { + document.addEventListener('mousedown', handleClickOutsideSelect); + return () => { + document.removeEventListener('mousedown', handleClickOutsideSelect); + }; + }, [isMenuOpen, componentName]); + useEffect(() => { setInputValue(findDefaultItem(advanced ? schema : options)); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -443,11 +466,7 @@ export const DropdownV2 = ({ _width={_width} top={'1px'} /> -
+
{ - setIsMultiselectOpen(true); - fireEvent('onFocus'); - }} - onMenuClose={() => { - setIsMultiselectOpen(false); - fireEvent('onBlur'); - }} onKeyDown={(e) => { - if (e.key === 'Enter' && !isMultiselectOpen) { + if (e.key === 'Enter' && !isMultiselectOpen && !isMultiSelectLoading) { setIsMultiselectOpen(true); + fireEvent('onFocus'); e.preventDefault(); } if (e.key === 'Escape' && isMultiselectOpen) { setIsMultiselectOpen(false); + fireEvent('onBlur'); e.preventDefault(); } }} From d2b05c986ecec3d775145e8968eddf7d1ae2ee61 Mon Sep 17 00:00:00 2001 From: devanshu052000 Date: Fri, 11 Apr 2025 00:41:41 +0530 Subject: [PATCH 04/15] Added show/hide clear button and search input functionality in dropdown --- .../WidgetManager/widgets/dropdownV2.js | 14 +++++ .../Components/DropdownV2/CustomMenuList.jsx | 59 ++++++++++--------- .../Components/DropdownV2/DropdownV2.jsx | 8 ++- .../WidgetManager/configs/dropdownV2.js | 14 +++++ .../apps/services/widget-config/dropdownV2.js | 14 +++++ 5 files changed, 80 insertions(+), 29 deletions(-) diff --git a/frontend/src/AppBuilder/WidgetManager/widgets/dropdownV2.js b/frontend/src/AppBuilder/WidgetManager/widgets/dropdownV2.js index cb90554e6b..d7534b25a8 100644 --- a/frontend/src/AppBuilder/WidgetManager/widgets/dropdownV2.js +++ b/frontend/src/AppBuilder/WidgetManager/widgets/dropdownV2.js @@ -75,6 +75,18 @@ export const dropdownV2Config = { accordian: 'Options', isFxNotRequired: true, }, + showClearBtn: { + type: 'toggle', + displayName: 'Show clear selection button', + validation: { schema: { type: 'boolean' }, defaultValue: true }, + section: 'additionalActions', + }, + showSearchInput: { + type: 'toggle', + displayName: 'Show search in options', + validation: { schema: { type: 'boolean' }, defaultValue: true }, + section: 'additionalActions', + }, loadingState: { type: 'toggle', displayName: 'Loading state', @@ -314,6 +326,8 @@ export const dropdownV2Config = { optionsLoadingState: { value: '{{false}}' }, sort: { value: 'asc' }, placeholder: { value: 'Select an option' }, + showClearBtn: { value: '{{true}}' }, + showSearchInput: { value: '{{true}}' }, visibility: { value: '{{true}}' }, disabledState: { value: '{{false}}' }, loadingState: { value: '{{false}}' }, diff --git a/frontend/src/Editor/Components/DropdownV2/CustomMenuList.jsx b/frontend/src/Editor/Components/DropdownV2/CustomMenuList.jsx index c606cc7560..0f1d7f04a3 100644 --- a/frontend/src/Editor/Components/DropdownV2/CustomMenuList.jsx +++ b/frontend/src/Editor/Components/DropdownV2/CustomMenuList.jsx @@ -22,6 +22,7 @@ const CustomMenuList = ({ selectProps, ...props }) => { fireEvent, inputValue, menuId, + showSearchInput, } = selectProps; const handleSelectAll = (e) => { @@ -47,34 +48,36 @@ const CustomMenuList = ({ selectProps, ...props }) => { className={cx('dropdown-multiselect-widget-custom-menu-list', { 'theme-dark dark-theme': darkMode })} onClick={(e) => e.stopPropagation()} > -
- - - - - onInputChange(e.currentTarget.value, { - action: 'input-change', - }) - } - onMouseDown={(e) => { - e.stopPropagation(); - e.target.focus(); - }} - onTouchEnd={(e) => { - e.stopPropagation(); - e.target.focus(); - }} - onFocus={onMenuInputFocus} - placeholder="Search" - className="dropdown-multiselect-widget-search-box" - /> -
+ {showSearchInput && ( +
+ + + + + onInputChange(e.currentTarget.value, { + action: 'input-change', + }) + } + onMouseDown={(e) => { + e.stopPropagation(); + e.target.focus(); + }} + onTouchEnd={(e) => { + e.stopPropagation(); + e.target.focus(); + }} + onFocus={onMenuInputFocus} + placeholder="Search" + className="dropdown-multiselect-widget-search-box" + /> +
+ )} {showAllOption && !optionsLoadingState && (