Skip to content

Instantly share code, notes, and snippets.

@notjamesheck
Forked from ohanhi/AutoExpand.elm
Created May 27, 2018 02:21
Show Gist options
  • Save notjamesheck/3fbadd00e25e304b26eaf29ac2198940 to your computer and use it in GitHub Desktop.
Save notjamesheck/3fbadd00e25e304b26eaf29ac2198940 to your computer and use it in GitHub Desktop.
A pure Elm auto expanding text area
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