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 1/3] 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 From 28d32c1a46a2837f529b9de4e687876dbc3e933d Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja <1805317@kiit.ac.in> Date: Fri, 15 Dec 2023 11:30:28 +0530 Subject: [PATCH 2/3] feat: added description on hover. --- src/components/InputFields.res | 2 ++ src/components/InputFields.resi | 39 ++++++++++++++------------------- src/components/SelectBox.res | 2 ++ 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/components/InputFields.res b/src/components/InputFields.res index d784b24dd..b93f7325e 100644 --- a/src/components/InputFields.res +++ b/src/components/InputFields.res @@ -218,6 +218,7 @@ let selectInput = ( ~ellipsisOnly=false, ~showBtnTextToolTip=false, ~dropdownClassName="", + ~descriptionOnHover=false, (), ) => { let accessHook = useGetAccessLevel() @@ -252,6 +253,7 @@ let selectInput = ( ellipsisOnly showBtnTextToolTip dropdownClassName + descriptionOnHover /> } diff --git a/src/components/InputFields.resi b/src/components/InputFields.resi index 548a553cf..33520a2b6 100644 --- a/src/components/InputFields.resi +++ b/src/components/InputFields.resi @@ -31,7 +31,7 @@ let selectInput: ( ~customButtonStyle: Js.String2.t=?, ~textStyle: string=?, ~marginTop: string=?, - ~customStyle: string=?, + ~customStyle: Js.String2.t=?, ~searchable: bool=?, ~showBorder: bool=?, ~showToolTipOptions: bool=?, @@ -43,16 +43,16 @@ let selectInput: ( ~fixedDropDownDirection: SelectBox.direction=?, ~customButton: React.element=?, ~buttonType: Button.buttonType=?, - ~dropdownCustomWidth: string=?, + ~dropdownCustomWidth: Js.String2.t=?, ~allowButtonTextMinWidth: bool=?, - ~setExtSearchString: (string => string) => unit=?, - ~textStyleClass: string=?, + ~setExtSearchString: ('b => string) => unit=?, + ~textStyleClass: Js.String2.t=?, ~ellipsisOnly: bool=?, ~showBtnTextToolTip: bool=?, ~dropdownClassName: string=?, + ~descriptionOnHover: bool=?, unit, ) => React.element - let asyncSelectInput: ( ~input: ReactFinalForm.fieldRenderPropsInput, ~url: Js.String2.t=?, @@ -123,7 +123,7 @@ let multiSelectInput: ( ~searchable: bool=?, ~showBorder: bool=?, ~optionRigthElement: React.element=?, - ~customStyle: string=?, + ~customStyle: Js.String2.t=?, ~customMargin: string=?, ~customButtonStyle: Js.String2.t=?, ~hideBorder: bool=?, @@ -135,7 +135,7 @@ let multiSelectInput: ( ~isHorizontal: bool=?, ~fullLength: bool=?, ~fixedDropDownDirection: SelectBox.direction=?, - ~dropdownCustomWidth: string=?, + ~dropdownCustomWidth: Js.String2.t=?, ~customMarginStyle: string=?, ~buttonTextWeight: string=?, ~marginTop: string=?, @@ -154,13 +154,12 @@ let multiSelectInput: ( ~leftIcon: Button.iconType=?, ~customBackColor: string=?, ~customSelectAllStyle: string=?, - ~onItemSelect: (ReactEvent.Mouse.t, string) => unit=?, + ~onItemSelect: (JsxEvent.Mouse.t, Js_string.t) => unit=?, ~wrapBasis: string=?, ~dropdownClassName: string=?, ~baseComponentMethod: bool => React.element=?, unit, ) => React.element - let btnGroupInput: ( ~input: ReactFinalForm.fieldRenderPropsInput, ~options: array, @@ -180,11 +179,11 @@ let radioInput: ( ~optionSize: CheckBoxIcon.size=?, ~isHorizontal: bool=?, ~deselectDisable: bool=?, - ~customStyle: string=?, + ~customStyle: Js.String2.t=?, ~baseComponentCustomStyle: string=?, ~customSelectStyle: string=?, ~fill: string=?, - ~maxHeight: string=?, + ~maxHeight: Js.String2.t=?, unit, ) => React.element let checkboxInput: ( @@ -196,14 +195,14 @@ let checkboxInput: ( ~disableSelect: bool=?, ~buttonText: Js.String2.t=?, ~placeholder: 'a, - ~maxHeight: string=?, + ~maxHeight: Js.String2.t=?, ~searchable: bool=?, ~searchInputPlaceHolder: string=?, - ~dropdownCustomWidth: string=?, + ~dropdownCustomWidth: Js.String2.t=?, ~customSearchStyle: string=?, ~customLabelStyle: string=?, ~customMarginStyle: string=?, - ~customStyle: string=?, + ~customStyle: Js.String2.t=?, ~checkboxDimension: string=?, ~wrapBasis: string=?, unit, @@ -320,7 +319,6 @@ let multipleFileInput: ( ~pointerDisable: bool=?, unit, ) => React.element - let csvFileUploadInput: ( ~input: ReactFinalForm.fieldRenderPropsInput, ~placeholder: 'a, @@ -329,7 +327,6 @@ let csvFileUploadInput: ( ~messageId: string, unit, ) => React.element - let imageInput: ( ~input: ReactFinalForm.fieldRenderPropsInput, ~placeholder: 'a, @@ -394,7 +391,6 @@ let datePickerInput: ( ~format: string=?, unit, ) => React.element - let singleDatePickerInput: ( ~input: ReactFinalForm.fieldRenderPropsInput, ~placeholder: 'a, @@ -406,7 +402,7 @@ let singleDatePickerInput: ( ~currentDateMinuteFormat: Js.String2.t=?, ~currentDateSecondsFormat: Js.String2.t=?, ~customButtonStyle: Js.String2.t=?, - ~newThemeCustomButtonStyle: Js.String2.t=?, + ~newThemeCustomButtonStyle: string=?, ~calendarContaierStyle: string=?, ~buttonSize: Button.buttonSize=?, ~showTime: bool=?, @@ -559,7 +555,6 @@ let multiLineTextInput: ( ~maxLength: int=?, unit, ) => React.element - let fieldWithMessage: ( (~input: ReactFinalForm.fieldRenderPropsInput, ~placeholder: 'a) => React.element, ~input: ReactFinalForm.fieldRenderPropsInput, @@ -581,7 +576,7 @@ let passwordCreateField: ( ~leftIcon: React.element=?, unit, ) => React.element -let passwordFieldWithCheckChips: ( +let passwordFieldWithCheckWindow: ( ~input: ReactFinalForm.fieldRenderPropsInput, ~placeholder: string, ~leftIcon: React.element=?, @@ -589,11 +584,11 @@ let passwordFieldWithCheckChips: ( ~customStyle: string=?, ~customPaddingClass: string=?, ~customTextStyle: string=?, - ~specialCharatersInfoText: Js.String2.t=?, + ~specialCharatersInfoText: string=?, ~customDashboardClass: string=?, unit, ) => React.element -let passwordFieldWithCheckWindow: ( +let passwordFieldWithCheckChips: ( ~input: ReactFinalForm.fieldRenderPropsInput, ~placeholder: string, ~leftIcon: React.element=?, diff --git a/src/components/SelectBox.res b/src/components/SelectBox.res index 42d98ee53..af3e7b1e0 100644 --- a/src/components/SelectBox.res +++ b/src/components/SelectBox.res @@ -2587,6 +2587,8 @@ let make = ( ?maxHeight ?searchInputPlaceHolder showSearchIcon + descriptionOnHover + showToolTipOptions /> } } From 33330f31fccf5980793b3958cc15315d48148f33 Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja <1805317@kiit.ac.in> Date: Mon, 18 Dec 2023 15:12:14 +0530 Subject: [PATCH 3/3] fix: Comments addressed --- src/components/SelectBox.res | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/SelectBox.res b/src/components/SelectBox.res index 3ebd12a41..9706c7d6e 100644 --- a/src/components/SelectBox.res +++ b/src/components/SelectBox.res @@ -1178,16 +1178,14 @@ module RenderListItemInBaseRadio = { | Some(str) =>
string_of_int} className="flex flex-row"> listItemComponent - {if isHorizontal { - React.null - } else { +
} /> - }} + | None => listItemComponent }