From 42a805f446051d0edcc2f25b57a5f5aa776a1103 Mon Sep 17 00:00:00 2001 From: Tessa Kelly <tessakkelly@gmail.com> Date: Mon, 22 Nov 2021 11:39:11 -0800 Subject: [PATCH] Replace intermediary InternalConfig structure --- src/Nri/Ui/RadioButton/V3.elm | 194 +++++++++++----------------------- 1 file changed, 64 insertions(+), 130 deletions(-) diff --git a/src/Nri/Ui/RadioButton/V3.elm b/src/Nri/Ui/RadioButton/V3.elm index ebd4e454..2759012a 100644 --- a/src/Nri/Ui/RadioButton/V3.elm +++ b/src/Nri/Ui/RadioButton/V3.elm @@ -276,121 +276,58 @@ maybeAttr attr maybeValue = {-| View a single radio button. -Renders nothing if the attributes list does not contain value, name, and valueToString. -} view : String -> List (Attribute value msg) -> Html msg view label attributes = let - config_ = + config = applyConfig attributes emptyConfig + + eventsAndValues = + applyEvents attributes + + name_ = + -- TODO: name should probably be a required property, + -- since radio button group keyboard behavior won't + -- work without it + case config.name of + Just n -> + n + + Nothing -> + "default-radio-button-group" + + stringValue = + Maybe.map2 (\f v -> f v) eventsAndValues.valueToString eventsAndValues.value + |> Maybe.withDefault "default-radio-value" + + id_ = + name_ ++ "-" ++ dasherize (toLower stringValue) + + isChecked = + eventsAndValues.selectedValue == eventsAndValues.value + + isLocked = + Maybe.map2 PremiumLevel.allowedFor config.contentPremiumLevel config.teacherPremiumLevel + |> Maybe.withDefault True + |> not + + ( disclosureId, disclosureElement ) = + case ( eventsAndValues.disclosedContent, isChecked ) of + ( [], _ ) -> + ( Nothing, text "" ) + + ( _, False ) -> + ( Nothing, text "" ) + + ( (_ :: _) as childNodes, True ) -> + ( Just (id_ ++ "-disclosure-content") + , span [ id (id_ ++ "-disclosure-content") ] + childNodes + ) in - case internalConfig label config_ (applyEvents attributes) of - Just config -> - view_ config - - _ -> - text "no radio button here" - - -type alias InternalConfig value msg = - { -- user specified Attributes - name : String - , label : String - , teacherPremiumLevel : Maybe PremiumLevel - , contentPremiumLevel : Maybe PremiumLevel - , isDisabled : Bool - , describedByIds : List String - , hideLabel : Bool - - -- user specified messages and values TODO unpack eventsAndValues - , value : value - , selectedValue : Maybe value - , onSelect : Maybe (value -> msg) - , valueToString : value -> String - , premiumMsg : Maybe msg - , disclosedContent : List (Html msg) - , containerCss : List Css.Style - - -- computed values that both view helpers need - , isChecked : Bool - , isLocked : Bool - , showPennant : Bool - , id : String - , disclosureIdAndElement : Maybe ( String, List (Html msg) ) - } - - -internalConfig : String -> Config -> EventsAndValues value msg -> Maybe (InternalConfig value msg) -internalConfig label config eventsAndValues = - case ( eventsAndValues.value, config.name, eventsAndValues.valueToString ) of - ( Just value_, Just name_, Just valueToString_ ) -> - let - isChecked = - -- why not guard and make sure neither is Nothing? - -- Because if value is Nothing we do not render a radio - eventsAndValues.selectedValue - == eventsAndValues.value - - id_ = - name_ ++ "-" ++ (dasherize <| toLower <| valueToString_ value_) - - disclosureId = - id_ ++ "-disclosure-content" - in - Just - { name = name_ - , label = label - , teacherPremiumLevel = config.teacherPremiumLevel - , contentPremiumLevel = config.contentPremiumLevel - , isDisabled = config.isDisabled - , describedByIds = config.describedByIds - , hideLabel = config.hideLabel - , value = value_ - , selectedValue = eventsAndValues.selectedValue - , onSelect = eventsAndValues.onSelect - , valueToString = valueToString_ - , premiumMsg = eventsAndValues.premiumMsg - , disclosedContent = eventsAndValues.disclosedContent - , isChecked = isChecked - , containerCss = config.containerCss - , isLocked = - case ( config.contentPremiumLevel, config.teacherPremiumLevel ) of - ( Just contentPremiumLevel, Just teacherPremiumLevel ) -> - not <| - PremiumLevel.allowedFor - contentPremiumLevel - teacherPremiumLevel - - _ -> - False - , showPennant = - case eventsAndValues.premiumMsg of - Just _ -> - True - - _ -> - False - , id = id_ - , disclosureIdAndElement = - case ( eventsAndValues.disclosedContent, isChecked ) of - ( [], _ ) -> - Nothing - - ( _, False ) -> - Nothing - - ( (_ :: _) as childNodes, True ) -> - Just <| ( disclosureId, childNodes ) - } - - _ -> - Nothing - - -view_ : InternalConfig value msg -> Html msg -view_ config = Html.span - [ id (config.id ++ "-container") + [ id (id_ ++ "-container") , classList [ ( "Nri-RadioButton-PremiumClass", config.showPennant ) ] , css [ position relative @@ -407,19 +344,19 @@ view_ config = , Css.batch config.containerCss ] ] - [ radio config.name - (config.valueToString config.value) - config.isChecked - [ id config.id - , Widget.disabled (config.isLocked || config.isDisabled) - , case ( config.onSelect, config.isDisabled ) of - ( Just onSelect_, False ) -> - onClick (onSelect_ config.value) + [ radio name_ + stringValue + isChecked + [ id id_ + , Widget.disabled (isLocked || config.isDisabled) + , case ( eventsAndValues.onSelect, eventsAndValues.value, config.isDisabled ) of + ( Just onSelect_, Just value_, False ) -> + onClick (onSelect_ value_) _ -> Attributes.none , class "Nri-RadioButton-HiddenRadioInput" - , maybeAttr (Tuple.first >> Aria.controls) config.disclosureIdAndElement + , maybeAttr Aria.controls disclosureId , case config.describedByIds of (_ :: _) as describedByIds -> Aria.describedBy describedByIds @@ -445,12 +382,12 @@ view_ config = ] ] , Html.label - [ for config.id + [ for id_ , classList [ ( "Nri-RadioButton-RadioButton", True ) - , ( "Nri-RadioButton-RadioButtonChecked", config.isChecked ) + , ( "Nri-RadioButton-RadioButtonChecked", isChecked ) ] - , css <| + , css [ position relative , outline Css.none , margin zero @@ -471,9 +408,9 @@ view_ config = ] ] [ radioInputIcon - { isLocked = config.isLocked + { isLocked = isLocked , isDisabled = config.isDisabled - , isChecked = config.isChecked + , isChecked = isChecked } , span (if config.showPennant then @@ -503,9 +440,11 @@ view_ config = else [] ] - [ Html.text config.label ] - , case ( config.hideLabel, config.premiumMsg ) of + [ Html.text label ] + , case ( config.hideLabel, eventsAndValues.premiumMsg ) of ( False, Just premiumMsg ) -> + -- TODO: should this flag show when the content premium + -- level is Free?? I somewhat think not! ClickableSvg.button "Premium" Pennant.premiumFlag [ ClickableSvg.onClick premiumMsg @@ -518,12 +457,7 @@ view_ config = text "" ] ] - , case config.disclosureIdAndElement of - Just ( id_, childNodes ) -> - span [ id id_ ] childNodes - - Nothing -> - text "" + , disclosureElement ]