| -- Copyright 2020 The Fuchsia Authors. All rights reserved. |
| -- Use of this source code is governed by a BSD-style license that can be |
| -- found in the LICENSE file. |
| |
| |
| module Window exposing |
| ( Model |
| , Msg(..) |
| , init |
| , isAbsent |
| , subscriptions |
| , update |
| , view |
| ) |
| |
| {-| This module implements modal windows. |
| |
| A modal window is a window placed on top of the main app content (which is |
| dimmed and disabled). The user can dismiss the window by clicking anywhere |
| outside it, or pressing Escape or Return. |
| |
| -} |
| |
| import Browser.Events |
| import Html exposing (Html) |
| import Html.Attributes as Attributes |
| import Html.Events as Events |
| import Json.Decode as Decode |
| |
| |
| |
| ------------- MODEL ------------------------------------------------------------ |
| |
| |
| type alias Model a = |
| Maybe a |
| |
| |
| init : Model a |
| init = |
| Nothing |
| |
| |
| isAbsent : Model a -> Bool |
| isAbsent model = |
| case model of |
| Just _ -> |
| False |
| |
| Nothing -> |
| True |
| |
| |
| |
| ------------- UPDATE ----------------------------------------------------------- |
| |
| |
| type Msg a |
| = NoOp |
| | Show a |
| | Hide |
| |
| |
| update : Msg a -> Model a -> Model a |
| update msg model = |
| case msg of |
| NoOp -> |
| model |
| |
| Show window -> |
| Just window |
| |
| Hide -> |
| Nothing |
| |
| |
| |
| ------------- SUBSCRIPTIONS ---------------------------------------------------- |
| |
| |
| subscriptions : Model a -> Sub (Msg a) |
| subscriptions model = |
| case model of |
| Just _ -> |
| Browser.Events.onKeyDown keyDownEvent |
| |
| _ -> |
| Sub.none |
| |
| |
| keyDownEvent : Decode.Decoder (Msg a) |
| keyDownEvent = |
| Decode.field "key" Decode.string |
| |> Decode.map |
| (\key -> |
| -- For the Help window, catching Enter here is redundant because |
| -- the focus will still be on the button, and pressing enter |
| -- again will click it and hide the window. But for the Settings |
| -- window it is needed since focus might be on a form input. The |
| -- toggle behavior on the button is still useful so that |
| -- spacebar hides the window when the button is still focused. |
| if key == "Enter" || key == "Escape" then |
| Hide |
| |
| else |
| NoOp |
| ) |
| |
| |
| |
| ------------- VIEW ------------------------------------------------------------- |
| |
| |
| view : (a -> Html msg) -> (Msg a -> msg) -> Model a -> Html msg |
| view windowView toMsg model = |
| case model of |
| Nothing -> |
| Html.text "" |
| |
| Just window -> |
| Html.div |
| [ Attributes.class "modal-container" |
| , Events.onClick (toMsg Hide) |
| ] |
| [ Html.div |
| [ Attributes.id modalBoxId |
| , Attributes.class "modal-box" |
| |
| -- Prevent clicking the box itself from hiding it. |
| , Events.stopPropagationOn "click" |
| (Decode.succeed ( toMsg NoOp, True )) |
| ] |
| [ windowView window ] |
| ] |
| |
| |
| modalBoxId : String |
| modalBoxId = |
| "ModalBox" |