- 
      
 - 
        
Save notjamesheck/3fbadd00e25e304b26eaf29ac2198940 to your computer and use it in GitHub Desktop.  
    A pure Elm auto expanding text area
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | module AutoExpand exposing (main) | |
| -- https://embed.ellie-app.com/Gnv9Bznh4na1/0 | |
| import Html exposing (Html, div, p, br, textarea, text) | |
| import Html.Attributes exposing (rows, style) | |
| import Html.Events exposing (onInput, on) | |
| import Json.Decode exposing (Decoder, field, at, map2, int, string) | |
| type alias Model = | |
| { rows : Int | |
| , inputText : String | |
| } | |
| type alias Config = | |
| { padding : Float | |
| , lineHeight : Float | |
| , minRows : Int | |
| , maxRows : Int | |
| } | |
| config : Config | |
| config = | |
| { padding = 10 | |
| , lineHeight = 20 | |
| , minRows = 1 | |
| , maxRows = 4 | |
| } | |
| initModel : Model | |
| initModel = | |
| { rows = config.minRows | |
| , inputText = "" | |
| } | |
| type Msg | |
| = NewValues String Int | |
| update : Msg -> Model -> ( Model, Cmd Msg ) | |
| update msg model = | |
| case msg of | |
| NewValues inputText height -> | |
| ( { model | |
| | inputText = inputText | |
| , rows = getRows height | |
| } | |
| , Cmd.none | |
| ) | |
| view : Model -> Html Msg | |
| view model = | |
| div [ containerStyle ] | |
| [ div | |
| [ style [ ( "width", "200px" ) ] | |
| ] | |
| [ textarea | |
| [ on "input" inputDecoder | |
| , rows model.rows | |
| , Html.Attributes.value model.inputText | |
| , textareaStyles model.rows | |
| ] | |
| [] | |
| , p [] | |
| [ text ("Rows: " ++ toString model.rows) | |
| , br [] [] | |
| , text ("Min: " ++ toString config.minRows) | |
| , br [] [] | |
| , text ("Max: " ++ toString config.maxRows) | |
| ] | |
| ] | |
| ] | |
| getRows : Int -> Int | |
| getRows scrollHeight = | |
| ((toFloat scrollHeight - 2 * config.padding) / config.lineHeight) | |
| |> ceiling | |
| |> clamp config.minRows config.maxRows | |
| inputDecoder : Decoder Msg | |
| inputDecoder = | |
| map2 NewValues | |
| (at [ "target", "value" ] string) | |
| (at [ "target", "scrollHeight" ] int) | |
| containerStyle : Html.Attribute msg | |
| containerStyle = | |
| style | |
| [ ( "background-color", "rebeccapurple" ) | |
| , ( "color", "white" ) | |
| , ( "font-family", "sans-serif" ) | |
| , ( "width", "100vw" ) | |
| , ( "height", "100vh" ) | |
| , ( "display", "flex" ) | |
| , ( "align-items", "center" ) | |
| , ( "justify-content", "center" ) | |
| , ( "flex-direction", "column" ) | |
| ] | |
| textareaStyles : Int -> Html.Attribute msg | |
| textareaStyles rowCount = | |
| style | |
| [ ( "padding", toString config.padding ++ "px" ) | |
| , ( "border", "0 none" ) | |
| , ( "border-radius", "2px" ) | |
| , ( "box-sizing", "border-box" ) | |
| , ( "line-height", toString config.lineHeight ++ "px" ) | |
| , ( "width", "100%" ) | |
| , ( "overflow" | |
| , if rowCount <= config.maxRows then | |
| "visible" | |
| else | |
| "scroll-y" | |
| ) | |
| ] | |
| main : Program Never Model Msg | |
| main = | |
| Html.program | |
| { view = view | |
| , update = update | |
| , subscriptions = \_ -> Sub.none | |
| , init = ( initModel, Cmd.none ) | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment