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

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 Chip.onClick from being called when this is clicked

on : String -> Json.Decoder m -> Property m

Add custom event handlers

onClick : msg -> Property msg

Add an onClick handler to the chip

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

{-| 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
@docs on, onClick

-}

import Html exposing (Attribute, Html)
import Html.Events
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)
    , listeners : List (Html.Attribute msg)
    }


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


{-| 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 icon =
    Options.set (\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 link =
    Options.set (\config -> { config | deleteLink = Just (Html.Attributes.href link) })


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

NOTE. This stops propagation and prevents default to stop `Chip.onClick` from being called
when this is clicked
-}
deleteClick : msg -> Property msg
deleteClick msg =
    -- We want to prevent the onClick of the Chip itself being called when clicking on the delete action
    Options.set
        (\config ->
            { config
                | deleteClick =
                    Just
                        (Html.Events.onWithOptions "click"
                            { stopPropagation = True, preventDefault = True }
                            (Json.succeed msg)
                        )
            }
        )


{-| Add custom event handlers
-}
on : String -> Json.Decoder m -> Property m
on event decoder =
    Options.set
        (\config ->
            { config
                | listeners = config.listeners ++ [ (Html.Events.on event decoder) ]
            }
        )


{-| Add an `onClick` handler to the chip
-}
onClick : msg -> Property msg
onClick msg =
    on "click" (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 =
            Options.collect defaultConfig props

        config =
            summary.config

        listeners =
            config.listeners

        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 (cs "mdl-chip--contact") isContact
             , Options.when (cs "mdl-chip--deletable") isDeletable
             , Internal.attribute <| Helpers.blurOn "mouseup"
             , Internal.attribute <| Helpers.blurOn "mouseleave"
             , Internal.attribute <| Helpers.blurOn "touchend"
             ]
                ++ props
            )
            listeners
            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