From 763f048008d29ce1a8fa4673e223a47bac678e85 Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja <1805317@kiit.ac.in> Date: Thu, 14 Dec 2023 16:38:48 +0530 Subject: [PATCH] feat: group-drop-down-component-changes --- src/components/SelectBox.res | 243 +++++++++++++++++++++++++--------- src/components/SelectBox.resi | 78 +++++++---- 2 files changed, 235 insertions(+), 86 deletions(-) diff --git a/src/components/SelectBox.res b/src/components/SelectBox.res index 6e36e5bcd..42d98ee53 100644 --- a/src/components/SelectBox.res +++ b/src/components/SelectBox.res @@ -364,10 +364,12 @@ type dropdownOptionWithoutOptional = { description: option, iconStroke: string, textColor: string, + optGroup: string, } type dropdownOption = { label: string, value: string, + optGroup?: string, isDisabled?: bool, icon?: Button.iconType, description?: string, @@ -384,6 +386,7 @@ let makeNonOptional = (dropdownOption: dropdownOption): dropdownOptionWithoutOpt description: dropdownOption.description, iconStroke: dropdownOption.iconStroke->Belt.Option.getWithDefault(""), textColor: dropdownOption.textColor->Belt.Option.getWithDefault(""), + optGroup: dropdownOption.optGroup->Belt.Option.getWithDefault("-"), } } @@ -1104,6 +1107,123 @@ module BaseSelectButton = { } } + +module RenderListItemInBaseRadio = { + @react.component + let make = ( + ~newOptions: Js.Array2.t, + ~value, + ~descriptionOnHover, + ~isDropDown, + ~textIconPresent, + ~searchString, + ~optionSize, + ~isSelectedStateMinus, + ~onItemClick, + ~fill, + ~customStyle, + ~isMobileView, + ~listFlexDirection, + ~customSelectStyle, + ~textOverflowClass, + ~showToolTipOptions, + ~textEllipsisForDropDownOptions, + ~isHorizontal, + ~customMarginStyleOfListItem="mx-3 py-2 gap-2", + ) => { + newOptions + ->Js.Array2.mapi((option, i) => { + let isSelected = switch value->Js.Json.decodeString { + | Some(str) => option.value === str + | None => false + } + + let description = descriptionOnHover ? option.description : None + let leftVacennt = isDropDown && textIconPresent && option.icon === NoIcon + let listItemComponent = + + + if !descriptionOnHover { + switch option.description { + | Some(str) => +
string_of_int} className="flex flex-row"> + listItemComponent + {if isHorizontal { + React.null + } else { + + +
} + /> + }} + + | None => listItemComponent + } + } else { + listItemComponent + } + }) + ->React.array + } +} + +let getHashMappedOptionValues = (options: array) => { + let hashMappedOptions = options->Array.reduce(Js.Dict.empty(), ( + acc, + ele: dropdownOptionWithoutOptional, + ) => { + if acc->Dict.get(ele.optGroup)->Option.isNone { + acc->Js.Dict.set(ele.optGroup, [ele]) + } else { + acc->Dict.get(ele.optGroup)->Option.getWithDefault([])->Array.push(ele)->ignore + } + acc + }) + + hashMappedOptions +} + +let getSortedKeys = hashMappedOptions => { + hashMappedOptions + ->Dict.keysToArray + ->Js.Array2.sortInPlaceWith((a, b) => { + switch (a, b) { + | ("-", _) => 1 + | (_, "-") => -1 + | (_, _) => String.compare(a, b)->Belt.Float.toInt + } + }) +} + module BaseRadio = { @react.component let make = ( @@ -1144,7 +1264,14 @@ module BaseRadio = { let options = React.useMemo1(() => { options->Js.Array2.map(makeNonOptional) }, [options]) - // to set width of dropdown, + + let hashMappedOptions = getHashMappedOptionValues(options) + + let isNonGrouped = + hashMappedOptions->Dict.get("-")->Option.getWithDefault([])->Array.length === + options->Array.length + + let (optgroupKeys, setOptgroupKeys) = React.useState(_ => getSortedKeys(hashMappedOptions)) let (searchString, setSearchString) = React.useState(() => "") React.useEffect1(() => { @@ -1235,7 +1362,7 @@ module BaseRadio = { } else { options } - if searchString != "" { + if searchString->Js.String2.length != 0 { let options = options->Js.Array2.filter(option => { shouldDisplay(option) }) @@ -1243,11 +1370,19 @@ module BaseRadio = { addDynamicValue && !(options->Js.Array2.map(item => item.value)->Js.Array2.includes(searchString)) ) { - options->Js.Array2.concat([searchString]->makeOptions->Js.Array2.map(makeNonOptional)) + if isNonGrouped { + options->Js.Array2.concat([searchString]->makeOptions->Js.Array2.map(makeNonOptional)) + } else { + options + } } else { + let hashMappedSearchedOptions = getHashMappedOptionValues(options) + let optgroupKeysForSearch = getSortedKeys(hashMappedSearchedOptions) + setOptgroupKeys(_ => optgroupKeysForSearch) options } } else { + setOptgroupKeys(_ => getSortedKeys(hashMappedOptions)) options } }, (searchString, options, selectedString)) @@ -1271,18 +1406,12 @@ module BaseRadio = { ? "animate-textTransition transition duration-400" : "animate-textTransitionOff transition duration-400"}`}> {switch searchable { - | Some(val) => - if val { - searchInputUI - } else { - React.null - } + | Some(val) => searchInputUI | None => - if isDropDown && (options->Js.Array2.length > 5 || addDynamicValue) { + Js.Array2.length > 5 || addDynamicValue)}> searchInputUI - } else { - React.null - } + }}
@@ -1290,67 +1419,57 @@ module BaseRadio = {
{React.string("No matching records found")}
+ } else if isNonGrouped { + } else { { - newOptions - ->Js.Array2.mapi((option, i) => { - let isSelected = switch value->Js.Json.decodeString { - | Some(str) => option.value === str - | None => false - } - - let description = descriptionOnHover ? option.description : None - let leftVacennt = isDropDown && textIconPresent && option.icon === NoIcon - let listItemComponent = - Array.mapWithIndex((ele, index) => { + string_of_int}> +

{ele->React.string}

+ Dict.get(ele) + ->Option.getWithDefault([])} + value + descriptionOnHover isDropDown - isSelected - fill + textIconPresent searchString - onClick={onItemClick(option.value, option.isDisabled)} - text=option.label optionSize isSelectedStateMinus - labelValue=option.label - multiSelect=false - icon=option.icon - leftVacennt - isDisabled=option.isDisabled + onItemClick + fill + customStyle isMobileView - description listFlexDirection - customStyle customSelectStyle - ?textOverflowClass - dataId=i - iconStroke=option.iconStroke + textOverflowClass showToolTipOptions textEllipsisForDropDownOptions - textColorClass={option.textColor} + isHorizontal + customMarginStyleOfListItem="ml-8 mx-3 py-2 gap-2" /> - - if !descriptionOnHover { - switch option.description { - | Some(str) => -
- listItemComponent - {if isHorizontal { - React.null - } else { - - -
} - /> - }} -
- | None => listItemComponent - } - } else { - listItemComponent - } + }) ->React.array } diff --git a/src/components/SelectBox.resi b/src/components/SelectBox.resi index d51532307..3071a426d 100644 --- a/src/components/SelectBox.resi +++ b/src/components/SelectBox.resi @@ -30,7 +30,7 @@ module ListItem: { ~icon: Button.iconType, ~leftVacennt: bool=?, ~showToggle: bool=?, - ~customStyle: string=?, + ~customStyle: Js.String2.t=?, ~serialNumber: option=?, ~isMobileView: bool=?, ~description: option=?, @@ -48,7 +48,7 @@ module ListItem: { ~iconStroke: string=?, ~showToolTipOptions: bool=?, ~textEllipsisForDropDownOptions: bool=?, - ~textColorClass: string=?, + ~textColorClass: Js.String2.t=?, ) => React.element } type dropdownOptionWithoutOptional = { @@ -59,10 +59,12 @@ type dropdownOptionWithoutOptional = { description: option, iconStroke: string, textColor: string, + optGroup: string, } type dropdownOption = { label: string, value: string, + optGroup?: string, isDisabled?: bool, icon?: Button.iconType, description?: string, @@ -96,12 +98,12 @@ module BaseSelect: { ~showSerialNumber: bool=?, ~heading: string=?, ~showSelectionAsChips: bool=?, - ~maxHeight: string=?, + ~maxHeight: Js.String2.t=?, ~searchable: bool=?, ~optionRigthElement: React.element=?, ~searchInputPlaceHolder: string=?, ~showSearchIcon: bool=?, - ~customStyle: string=?, + ~customStyle: Js.String2.t=?, ~customMargin: string=?, ~disableSelect: bool=?, ~deselectDisable: bool=?, @@ -126,9 +128,9 @@ module BaseSelect: { ~customSelectAllStyle: string=?, ~checkboxDimension: string=?, ~dropdownClassName: string=?, - ~onItemSelect: (ReactEvent.Mouse.t, string) => unit=?, + ~onItemSelect: (JsxEvent.Mouse.t, Js_string.t) => unit=?, ~wrapBasis: string=?, - ~preservedAppliedOptions: array=?, + ~preservedAppliedOptions: Js.Array2.t=?, ) => React.element } module BaseSelectButton: { @@ -155,6 +157,34 @@ module BaseSelectButton: { ~allowButtonTextMinWidth: bool=?, ) => React.element } +module RenderListItemInBaseRadio: { + @react.component + let make: ( + ~newOptions: Js.Array2.t, + ~value: Js.Json.t, + ~descriptionOnHover: bool, + ~isDropDown: bool, + ~textIconPresent: bool, + ~searchString: Js.String2.t, + ~optionSize: CheckBoxIcon.size, + ~isSelectedStateMinus: bool, + ~onItemClick: (string, bool, JsxEvent.Mouse.t) => unit, + ~fill: string, + ~customStyle: Js.String2.t, + ~isMobileView: bool, + ~listFlexDirection: string, + ~customSelectStyle: string, + ~textOverflowClass: option, + ~showToolTipOptions: bool, + ~textEllipsisForDropDownOptions: bool, + ~isHorizontal: bool, + ~customMarginStyleOfListItem: string=?, + ) => React.element +} +let getHashMappedOptionValues: array => Js.Dict.t< + array, +> +let getSortedKeys: RescriptCore.Dict.t<'a> => Js.Array2.t module BaseRadio: { @react.component let make: ( @@ -169,19 +199,19 @@ module BaseRadio: { ~deselectDisable: bool=?, ~onBlur: ReactEvent.Focus.t => unit=?, ~fill: string=?, - ~customStyle: string=?, + ~customStyle: Js.String2.t=?, ~searchable: bool=?, ~isMobileView: bool=?, ~customSearchStyle: string=?, ~descriptionOnHover: bool=?, ~addDynamicValue: bool=?, - ~dropdownCustomWidth: string=?, + ~dropdownCustomWidth: Js.String2.t=?, ~dropdownRef: React.ref>=?, ~showMatchingRecordsText: bool=?, ~fullLength: bool=?, ~selectedString: string=?, - ~setSelectedString: (string => string) => unit=?, - ~setExtSearchString: (string => string) => unit=?, + ~setSelectedString: ('a => Js_string.t) => unit=?, + ~setExtSearchString: ('b => string) => unit=?, ~listFlexDirection: string=?, ~baseComponentCustomStyle: string=?, ~customSelectStyle: string=?, @@ -216,7 +246,7 @@ module CustomUISearchOptionUI: { ~showMatchingRecordsText: bool=?, ~fullLength: bool=?, ~searchString: Js.String2.t, - ~setSearchString: ('a => string) => unit, + ~setSearchString: ('a => Js.String2.t) => unit, ~searchPlaceholder: string=?, ) => React.element } @@ -249,7 +279,7 @@ module BaseDropdown: { ~fixedDropDownDirection: direction=?, ~addButton: bool=?, ~marginTop: string=?, - ~customStyle: string=?, + ~customStyle: Js.String2.t=?, ~customSearchStyle: string=?, ~showSelectionAsChips: bool=?, ~showToolTip: bool=?, @@ -263,18 +293,18 @@ module BaseDropdown: { ~addDynamicValue: bool=?, ~showMatchingRecordsText: bool=?, ~hasApplyButton: bool=?, - ~dropdownCustomWidth: string=?, + ~dropdownCustomWidth: Js.String2.t=?, ~allowButtonTextMinWidth: bool=?, ~customMarginStyle: string=?, ~customButtonLeftIcon: Button.iconType=?, ~customTextPaddingClass: string=?, ~customButtonPaddingClass: string=?, ~customButtonIconMargin: string=?, - ~textStyleClass: string=?, + ~textStyleClass: Js.String2.t=?, ~buttonStyleOnDropDownOpened: string=?, - ~selectedString: string=?, - ~setSelectedString: (string => string) => unit=?, - ~setExtSearchString: (string => string) => unit=?, + ~selectedString: Js.String2.t=?, + ~setSelectedString: ('a => Js_string.t) => unit=?, + ~setExtSearchString: ('b => string) => unit=?, ~listFlexDirection: string=?, ~ellipsisOnly: bool=?, ~isPhoneDropdown: bool=?, @@ -282,7 +312,7 @@ module BaseDropdown: { ~showAllSelectedOptions: bool=?, ~buttonClickFn: string => unit=?, ~showSelectCountButton: bool=?, - ~maxHeight: string=?, + ~maxHeight: Js.String2.t=?, ~customBackColor: string=?, ~showToolTipOptions: bool=?, ~textEllipsisForDropDownOptions: bool=?, @@ -338,10 +368,10 @@ let make: ( ~customButtonStyle: Js.String2.t=?, ~textStyle: string=?, ~marginTop: string=?, - ~customStyle: string=?, + ~customStyle: Js.String2.t=?, ~showSelectionAsChips: bool=?, ~showToggle: bool=?, - ~maxHeight: string=?, + ~maxHeight: Js.String2.t=?, ~searchable: bool=?, ~fill: string=?, ~optionRigthElement: React.element=?, @@ -362,7 +392,7 @@ let make: ( ~customButton: React.element=?, ~descriptionOnHover: bool=?, ~fixedDropDownDirection: direction=?, - ~dropdownCustomWidth: string=?, + ~dropdownCustomWidth: Js.String2.t=?, ~allowButtonTextMinWidth: bool=?, ~baseComponent: React.element=?, ~baseComponentMethod: bool => React.element=?, @@ -372,8 +402,8 @@ let make: ( ~customTextPaddingClass: string=?, ~customButtonPaddingClass: string=?, ~customButtonIconMargin: string=?, - ~textStyleClass: string=?, - ~setExtSearchString: (string => string) => unit=?, + ~textStyleClass: Js.String2.t=?, + ~setExtSearchString: ('a => string) => unit=?, ~buttonStyleOnDropDownOpened: string=?, ~listFlexDirection: string=?, ~baseComponentCustomStyle: string=?, @@ -397,6 +427,6 @@ let make: ( ~textEllipsisForDropDownOptions: bool=?, ~showBtnTextToolTip: bool=?, ~dropdownClassName: string=?, - ~onItemSelect: (ReactEvent.Mouse.t, string) => unit=?, + ~onItemSelect: (JsxEvent.Mouse.t, Js_string.t) => unit=?, ~wrapBasis: string=?, ) => React.element