<commit_before>module Internal.Drawer.Implementation exposing
    ( Config
    , Property
    , Store
    , content
    , defaultConfig
    , emit
    , header
    , onClose
    , open
    , react
    , render
    , subs
    , subscriptions
    , subTitle
    , title
    , update
    , view
    )

import Html exposing (Html, text)
import Internal.Component as Component exposing (Index, Indexed)
import Internal.Drawer.Model exposing (Model, Msg(..), defaultModel)
import Internal.GlobalEvents as GlobalEvents
import Internal.Helpers as Helpers
import Internal.List.Implementation as Lists
import Internal.Msg
import Internal.Options as Options exposing (cs, css, many, styled, when)
import Json.Decode as Decode exposing (Decoder)


update : (Msg -> m) -> Msg -> Model -> ( Maybe Model, Cmd m )
update lift msg model =
    case msg of
        NoOp ->
            ( Nothing, Cmd.none )

        StartAnimation ( isOpen ) ->
            ( Just
                { model
                    | open = True
                    , closeOnAnimationEnd = not isOpen
                    , animating = True
                }
            , Cmd.none
            )

        EndAnimation ->
            ( Just
                { model
                    | open = if model.closeOnAnimationEnd then False else model.open
                    , animating = False
                    , closeOnAnimationEnd = False
                }
            , Cmd.none
            )


type alias Config m =
    { onClose : Maybe m
    , open : Bool
    }


defaultConfig : Config m
defaultConfig =
    { onClose = Nothing
    , open = False
    }


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


view : String -> (Msg -> m) -> Model -> List (Property m) -> List (Html m) -> Html m
view className lift model options nodes =
    let
        ({ config } as summary) =
            Options.collect defaultConfig options

        stateChanged =
            (not model.closeOnAnimationEnd) && ( (config.open) /= (model.open) )
    in
    styled Html.aside
        ( [ cs "mdc-drawer"
        , cs className
        , when stateChanged <|
            GlobalEvents.onTick (Decode.succeed (lift (StartAnimation config.open) ))

          -- In order for the closing animation to work, we need to
          -- keep the open class till the animation has ended
        , cs "mdc-drawer--open" |> when (config.open || model.open)

          -- Animate class needs to kick in as soon as drawer is
          -- opened. It's only used during opening.
        , cs "mdc-drawer--animate" |> when (config.open && (stateChanged || model.animating))

          -- Wait a frame once display is no longer "none", to establish basis for animation
        , cs "mdc-drawer--opening" |> when (config.open && model.animating)
        , cs "mdc-drawer--closing" |> when (not config.open && model.animating)

        , when model.animating (Options.on "transitionend" (Decode.succeed (lift EndAnimation)))

          -- TODO: Handle Esc key for modal and dismissible.
          -- TODO: Handle arrow keys (hard).<commit_msg>Prep drawer for handling Esc key, but couldn't get that to work<commit_after>module Internal.Drawer.Implementation exposing
    ( Config
    , Property
    , Store
    , content
    , defaultConfig
    , emit
    , header
    , onClose
    , open
    , react
    , render
    , subs
    , subscriptions
    , subTitle
    , title
    , update
    , view
    )

import Html exposing (Html, text)
import Internal.Component as Component exposing (Index, Indexed)
import Internal.Drawer.Model exposing (Model, Msg(..), defaultModel)
import Internal.GlobalEvents as GlobalEvents
import Internal.Helpers as Helpers
import Internal.List.Implementation as Lists
import Internal.Msg
import Internal.Options as Options exposing (cs, css, many, styled, when)
import Json.Decode as Decode exposing (Decoder)


update : (Msg -> m) -> Msg -> Model -> ( Maybe Model, Cmd m )
update lift msg model =
    case msg of
        NoOp ->
            ( Nothing, Cmd.none )

        StartAnimation ( isOpen ) ->
            ( Just
                { model
                    | open = True
                    , closeOnAnimationEnd = not isOpen
                    , animating = True
                }
            , Cmd.none
            )

        EndAnimation ->
            ( Just
                { model
                    | open = if model.closeOnAnimationEnd then False else model.open
                    , animating = False
                    , closeOnAnimationEnd = False
                }
            , Cmd.none
            )


type alias Config m =
    { onClose : Maybe m
    , open : Bool
    }


defaultConfig : Config m
defaultConfig =
    { onClose = Nothing
    , open = False
    }


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


view : String -> (Msg -> m) -> Model -> List (Property m) -> List (Html m) -> Html m
view className lift model options nodes =
    let
        ({ config } as summary) =
            Options.collect defaultConfig options

        stateChanged =
            (not model.closeOnAnimationEnd) && ( (config.open) /= (model.open) )
    in
    styled Html.aside
        ( [ cs "mdc-drawer"
        , cs className
        , when stateChanged <|
            GlobalEvents.onTick (Decode.succeed (lift (StartAnimation config.open) ))

          -- In order for the closing animation to work, we need to
          -- keep the open class till the animation has ended
        , cs "mdc-drawer--open" |> when (config.open || model.open)

          -- Animate class needs to kick in as soon as drawer is
          -- opened. It's only used during opening.
        , cs "mdc-drawer--animate" |> when (config.open && (stateChanged || model.animating))

          -- Wait a frame once display is no longer "none", to establish basis for animation
        , cs "mdc-drawer--opening" |> when (config.open && model.animating)
        , cs "mdc-drawer--closing" |> when (not config.open && model.animating)

        , when model.animating (Options.on "transitionend" (Decode.succeed (lift EndAnimation)))

        -- TODO: Handle Esc key for modal and dismissible.
        , Options.data "focustrap" "focustrap" |> when (not (String.isEmpty className) && ( config.open || model.open ) )
        , Options.on "keydown" <|
            Decode.map lift <|
                Decode.map2
                    (\key keyCode ->
                         if key == Just "Escape" || keyCode == 27 then
                             --Maybe.withDefault (lift NoOp) config.onClose
                             NoOp
                         else
                             --lift NoOp
                             NoOp
                    )
                    (Decode.oneOf
                         [ Decode.map Just (Decode.at [ "key" ] Decode.string)
                         , Decode.succeed Nothing
                         ]
                    )
                    (Decode.at [ "keyCode" ] Decode.int)

          -- TODO: Handle arrow keys (hard).
{'fraction_non_alphanumeric': 0.09222886421861656, 'fraction_numerical': 0.0004269854824935952, 'mean_word_length': 1.6477015825169556, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4996940', 'n_tokens_mistral': 1921, 'n_tokens_neox': 1825, 'n_words': 607}