This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.

Material.Chip

From the Material Design Lite documentation:

The Material Design Lite (MDL) chip component is a small, interactive element. Chips are commonly used for contacts, text, rules, icons, and photos.

See also the Material Design Specification.

Refer to this site for a live demo.

Types

type alias Property msg = Options.Property (Config msg) msg

Properties for Chip options.

type alias HtmlElement msg = List (Attribute msg) -> List (Html msg) -> Html msg

Alias for a Html m function. e.g. Html.div

type Content msg = Contact (HtmlElement msg) (List (Property msg)) (List (Html msg)) | Text (List (Property msg)) (List (Html msg)) | Action (HtmlElement msg) (List (Property msg)) (List (Html msg))

Chip can contain only specific kind of content

Elements

chip : HtmlElement msg -> List (Property msg) -> List (Content msg) -> Html msg

Create a chip contained in the given element

button : List (Property msg) -> List (Content msg) -> Html msg

Creates a chip using Html.button

span : List (Property msg) -> List (Content msg) -> Html msg

Creates a chip using Html.span

content : List (Property msg) -> List (Html msg) -> Content msg

Generate chip content

text : List (Property msg) -> String -> Content msg

Shorthand for Chip.content [] [ Html.text "text" ]

contact : HtmlElement msg -> List (Property msg) -> List (Html msg) -> Content msg

Create a chip contact contained in the given element

Properties

deleteIcon : String -> Property msg

Set the icon for the delete action

deleteLink : String -> Property msg

Set the link for the delete action.

NOTE. This turns the action to Html.a element

deleteClick : msg -> Property msg

Set the onClick for the delete action

NOTE. This stops propagation and prevents default to stop onClick from being called when this is clicked.

module Material.Chip
    exposing
        ( Property
        , HtmlElement
        , Content
        , chip
        , button
        , span
        , content
        , text
        , contact
        , deleteIcon
        , deleteLink
        , deleteClick
        )

{-| From the [Material Design Lite documentation](http://www.getmdl.io/components/index.html#chips-section):

> The Material Design Lite (MDL) chip component is a small, interactive element.
> Chips are commonly used for contacts, text, rules, icons, and photos.

See also the
[Material Design Specification](https://www.google.com/design/spec/components/chips.html).

Refer to [this site](http://debois.github.io/elm-mdl/#chips)
for a live demo.


# Types
@docs Property, HtmlElement, Content

# Elements
@docs chip, button, span
@docs content , text , contact

# Properties
@docs deleteIcon , deleteLink , deleteClick

-}

import Html exposing (Attribute, Html)
import Html.Attributes
import Material.Options as Options exposing (cs)
import Material.Icon as Icon
import Material.Options.Internal as Internal
import Material.Helpers as Helpers
import Json.Decode as Json


{-| Alias for a `Html m` function. e.g. `Html.div`
-}
type alias HtmlElement msg =
    List (Attribute msg) -> List (Html msg) -> Html msg


type alias Config msg =
    { deleteIcon : Maybe String
    , deleteLink : Maybe (Html.Attribute msg)
    , deleteClick : Maybe (Html.Attribute msg)
    }


defaultConfig : Config msg
defaultConfig =
    { deleteIcon = Nothing
    , deleteLink = Nothing
    , deleteClick = Nothing
    }


{-| Properties for Chip options.
-}
type alias Property msg =
    Options.Property (Config msg) msg


{-| Chip can contain only specific kind of content
-}
type Content msg
    = Contact (HtmlElement msg) (List (Property msg)) (List (Html msg))
    | Text (List (Property msg)) (List (Html msg))
    | Action (HtmlElement msg) (List (Property msg)) (List (Html msg))


{-| Set the icon for the delete action
-}
deleteIcon : String -> Property msg
deleteIcon =
    Internal.option
        << (\icon config -> { config | deleteIcon = Just icon })


{-| Set the link for the delete action.

NOTE. This turns the action to `Html.a` element
-}
deleteLink : String -> Property msg
deleteLink =
    Internal.option
        << (\link config -> { config | deleteLink = Just (Html.Attributes.href link) })


{-| Set the `onClick` for the delete action

NOTE. This stops propagation and prevents default to stop `onClick` from being
called when this is clicked.
-}
deleteClick : msg -> Property msg
deleteClick msg =
    Options.onWithOptions
      "click" 
       { stopPropagation = True, preventDefault = True }
       (Json.succeed msg)

type alias Priority =
    Int


priority : Content a -> Priority
priority item =
    case item of
        Contact _ _ _ ->
            0

        Text _ _ ->
            1

        Action _ _ _ ->
            2


{-| Renders a given `Content`
-}
renderItem : Content msg -> Html msg
renderItem item =
    case item of
        Contact element props content ->
            Options.styled element
                (cs "mdl-chip__contact" :: props)
                content

        Text props content ->
            Options.styled Html.span
                (cs "mdl-chip__text" :: props)
                content

        Action element props content ->
            Options.styled element
                (cs "mdl-chip__action" :: props)
                content


hasValue : Maybe a -> Bool
hasValue m =
    case m of
        Just _ ->
            True

        Nothing ->
            False


getActionElement : Config msg -> Maybe (Content msg)
getActionElement config =
    let
        hasIcon =
            hasValue config.deleteIcon

        hasLink =
            hasValue config.deleteLink

        hasClick =
            hasValue config.deleteClick

        icon =
            if hasIcon then
                Maybe.withDefault "" config.deleteIcon
            else if (hasLink || hasClick) then
                Maybe.withDefault "cancel" config.deleteIcon
            else
                ""

        actionElement =
            if hasLink then
                Html.a
            else
                Html.span

        link =
            case config.deleteLink of
                Just l ->
                    Internal.attribute l

                Nothing ->
                    Options.nop

        click =
            case config.deleteClick of
                Just c ->
                    Internal.attribute c

                Nothing ->
                    Options.nop

        isDeletable =
            hasIcon || hasLink || hasClick
    in
        if isDeletable then
            action actionElement
                [ link, click ]
                [ Icon.view icon [] ]
                |> Just
        else
            Nothing


{-| Creates a chip using `Html.button`
-}
button : List (Property msg) -> List (Content msg) -> Html msg
button props =
    chip Html.button ((Internal.attribute <| Html.Attributes.type_ "button") :: props)


{-| Creates a chip using `Html.span`
-}
span : List (Property msg) -> List (Content msg) -> Html msg
span =
    chip Html.span


{-| Create a chip contained in the given element
-}
chip : HtmlElement msg -> List (Property msg) -> List (Content msg) -> Html msg
chip element props items =
    let
        summary =
            Internal.collect defaultConfig props

        config =
            summary.config

        action =
            getActionElement config

        isDeletable =
            hasValue action

        withIcon =
            (case action of
                Just a ->
                    [ a ]

                Nothing ->
                    []
            )
                ++ items

        content =
            withIcon
                |> List.sortBy priority
                |> List.map renderItem

        isContact =
            List.any (\x -> priority x == 0) items
    in
        Options.styled element
            ([ cs "mdl-chip"
             , Options.when isContact (cs "mdl-chip--contact")
             , Options.when isDeletable (cs "mdl-chip--deletable")
             , Internal.attribute <| Helpers.blurOn "mouseup"
             , Internal.attribute <| Helpers.blurOn "mouseleave"
             , Internal.attribute <| Helpers.blurOn "touchend"
             ]
                ++ props)
            content


{-| Generate chip content
-}
content : List (Property msg) -> List (Html msg) -> Content msg
content =
    Text


{-| Shorthand for `Chip.content [] [ Html.text "text" ]`
-}
text : List (Property msg) -> String -> Content msg
text props txt =
    Text props [ Html.text txt ]


{-| Create a chip action contained in the given element
-}
action : HtmlElement msg -> List (Property msg) -> List (Html msg) -> Content msg
action =
    Action


{-| Create a chip contact contained in the given element
-}
contact : HtmlElement msg -> List (Property msg) -> List (Html msg) -> Content msg
contact =
    Contact