[{"name":"Emitter","comment":" This module allows you to create a page module or UI component that can emit `Msg` to your app. If you haven't checked the `Page` module in this package yet, it's recommended to start with `Page`, then move on to this module later. Some boilerplate code is required.\n\n\n# Terminology\n\nTo simplify the explanations throughout this document, let's introduce some terminology:\n\n  - `InnerMsg`\n      - The message type you define for use within the `Emitter.Program`.\n  - `AppMsg`\n      - The message type used by your application, which incorporates `Emitter.Program AppMsg` as a component.\n  - `EmittedValue`\n      - A type that the component emits.\n      - You will need to convert these values into `AppMsg` within _the main app's code_.\n\n\n# Example Code\n\nHere’s an example of how to define your user form component:\n\n    module UserForm exposing (User, program)\n\n    import Browser.Dom\n    import Emitter\n    import Html as H exposing (Html)\n    import Html.Attributes as HA\n    import Html.Events as HE\n    import Task\n\n    type alias Model =\n        { nameInput : String\n        , ageInput : String\n        , tried : Bool\n        }\n\n    init : () -> ( Model, Cmd Msg )\n    init _ =\n        ( { nameInput = \"\"\n          , ageInput = \"\"\n          , tried = False\n          }\n        , Cmd.none\n        )\n\n    type alias User =\n        { name : String\n        , age : Int\n        }\n\n    type Msg\n        = NoOp\n        | UserInputName String\n        | UserInputAge String\n        | SubmitButtonClicked\n        | Emit User\n\n    cmdEmission : User -> Cmd Msg\n    cmdEmission user =\n        -- This is the first piece of boilerplate code.\n        Task.perform Emit (Task.succeed user)\n\n    update : Msg -> Model -> ( Model, Cmd Msg )\n    update msg model =\n        case msg of\n            NoOp ->\n                ( model, Cmd.none )\n\n            UserInputName name ->\n                ( { model | nameInput = name }, Cmd.none )\n\n            UserInputAge age ->\n                ( { model | ageInput = age }, Cmd.none )\n\n            SubmitButtonClicked ->\n                let\n                    newModel =\n                        { model | tried = True }\n                in\n                if model.nameInput /= \"\" then\n                    case String.toInt model.ageInput of\n                        Just age ->\n                            if 0 <= age && age <= 150 then\n                                ( newModel, cmdEmission (User model.nameInput age) )\n\n                            else\n                                ( newModel, Browser.Dom.focus \"ageInputField\" |> Task.attempt (\\_ -> NoOp) )\n\n                        Nothing ->\n                            ( newModel, Browser.Dom.focus \"ageInputField\" |> Task.attempt (\\_ -> NoOp) )\n\n                else\n                    ( newModel, Browser.Dom.focus \"nameInputField\" |> Task.attempt (\\_ -> NoOp) )\n\n            Emit user ->\n                -- This is the second piece of boilerplate code.\n                -- You can copy and paste these lines!\n                -- It may seem like it causes an infinite loop, but that's not the case because the `Cmd` is captured by the anonymous function passed below as the first argument of `Emitter.element`.\n                ( model, cmdEmission user )\n\n    view : Model -> Html Msg\n    view model =\n        H.div []\n            [ if model.tried && model.nameInput == \"\" then\n                H.span [ HA.style \"color\" \"red\" ] [ H.text \"Your name must not be empty.\" ]\n\n              else\n                H.text \"\"\n            , H.br [] []\n            , H.input\n                [ HA.id \"nameInputField\"\n                , HA.type_ \"text\"\n                , HA.placeholder \"Input your name\"\n                , HA.value model.nameInput\n                , HE.onInput UserInputName\n                ]\n                []\n            , H.br [] []\n            , H.span [ HA.style \"color\" \"red\" ]\n                [ if not model.tried then\n                    H.text \"\"\n\n                  else if model.ageInput == \"\" then\n                    H.text \"Your age must not be empty.\"\n\n                  else\n                    case String.toInt model.ageInput of\n                        Nothing ->\n                            H.text \"Please input a valid integer.\"\n\n                        Just age ->\n                            if age < 0 then\n                                H.text \"Please come back after you are born.\"\n\n                            else if age > 150 then\n                                H.text \"You should contact Guinness World Records about your longevity.\"\n\n                            else\n                                H.text \"\"\n                ]\n            , H.br [] []\n            , H.input\n                [ HA.id \"ageInputField\"\n                , HA.type_ \"text\"\n                , HA.placeholder \"Input your age\"\n                , HA.value model.ageInput\n                , HE.onInput UserInputAge\n                ]\n                []\n            , H.br [] []\n            , H.button [ HE.onClick SubmitButtonClicked ] [ H.text \"Submit\" ]\n            ]\n\n    program : (User -> appMsg) -> Emitter.Program () appMsg\n    program =\n        Emitter.element\n            (\\msg ->\n                case msg of\n                    Emit user ->\n                        Just user\n\n                    _ ->\n                        Nothing\n            )\n            { init = init\n            , subscriptions = \\_ -> Sub.none\n            , update = update\n            , view = view\n            }\n\nThe module you defined can be used as follows:\n\n    module Main exposing (..)\n\n    import Browser\n    import Emitter\n    import Html as H exposing (Html)\n    import Html.Attributes as HA\n    import Html.Events\n    import UserForm exposing (User)\n\n    type alias Model =\n        { userForm : Emitter.Model Msg\n        , user : Maybe User\n        }\n\n    init : () -> ( Model, Cmd Msg )\n    init _ =\n        update\n            (Emitter.mapInit FormInitialized\n                (UserForm.program UserSubmitted)\n                ()\n            )\n            { userForm = Emitter.empty, user = Nothing }\n\n    type Msg\n        = FormInitialized ( Emitter.Model Msg, Cmd (Emitter.Msg Msg), Cmd Msg )\n        | GotFormMsg (Emitter.Msg Msg)\n        | UserSubmitted User\n\n    subscriptions : Model -> Sub Msg\n    subscriptions model =\n        Emitter.mapSubscriptions GotFormMsg model.userForm\n\n    update : Msg -> Model -> ( Model, Cmd Msg )\n    update msg model =\n        case msg of\n            FormInitialized ( emt, cmdInner, cmdMsg ) ->\n                ( { model | userForm = emt }\n                , Cmd.batch\n                    [ Cmd.map GotFormMsg cmdInner\n                    , cmdMsg\n                    ]\n                )\n\n            GotFormMsg m ->\n                let\n                    ( emt, cmdInner, cmdMsg ) =\n                        Emitter.update m model.userForm\n                in\n                ( { model | userForm = emt }\n                , Cmd.batch\n                    [ Cmd.map GotFormMsg cmdInner\n                    , cmdMsg\n                    ]\n                )\n\n            UserSubmitted u ->\n                ( { model | user = Just u }, Cmd.none )\n\n    view : Model -> Html Msg\n    view model =\n        H.div []\n            [ H.div [ HA.style \"border\" \"ridge 3px pink\" ]\n                [ Emitter.mapView GotFormMsg model.userForm ]\n            , case model.user of\n                Nothing ->\n                    H.text \"\"\n\n                Just user ->\n                    H.text <|\n                        \"Hello, \"\n                            ++ user.name\n                            ++ \"!\"\n            ]\n\n    main : Program () Model Msg\n    main =\n        Browser.element\n            { init = init\n            , subscriptions = subscriptions\n            , update = update\n            , view = view\n            }\n\nIf you want to try moving this code, `git clone` the corresponding repo.\n\n\n# Types\n\n@docs Model, Msg, Program\n\n\n# Creation\n\n@docs empty, element\n\n\n# Usage\n\n@docs mapInit, mapSubscriptions, mapView, update\n\n","unions":[{"name":"Model","comment":" A custom type that represents a UI module that can emit `AppMsg`. No type variables for its inner state or `InnerMsg` are needed.\n","args":["appMsg"],"cases":[]},{"name":"Msg","comment":" This `Emitter.Msg` value is used both to update the emitter state and to emit some value for the entire application. See the example above for more details.\n","args":["appMsg"],"cases":[]},{"name":"Program","comment":" A custom type representing the main program of your component module. This type of values can be passed to `Emitter.mapInit` with flag.\n","args":["flag","appMsg"],"cases":[]}],"aliases":[],"values":[{"name":"element","comment":" Similar to `Page.element`, but with two additional arguments:\n\n  - The first argument is a function that specifies how your component emits a value that can be captured outside the loop of `InnerMsg`.\n      - This function monitors all `InnerMsg`s.\n      - If the message is intended to emit a value to the main app, let it return `Just emittedValue`.\n      - Otherwise, return `Nothing`.\n  - The third argument is a converter from `EmittedValue` to `AppMsg`.\n      - Typically, the first and second arguments are defined in the component module, while the third and fourth arguments are defined in the main app module.\n\nBe sure to check the example code in the [GitHub repository](https://github.com/kudzu-forest/elm-page).\n\n","type":"(msg -> Maybe.Maybe emitted) -> { init : flag -> ( model, Platform.Cmd.Cmd msg ), subscriptions : model -> Platform.Sub.Sub msg, update : msg -> model -> ( model, Platform.Cmd.Cmd msg ), view : model -> Html.Html msg } -> (emitted -> appMsg) -> Emitter.Program flag appMsg"},{"name":"empty","comment":" Similar to `Page.empty`.\n","type":"Emitter.Model appMsg"},{"name":"mapInit","comment":" Functions similarly to `Page.mapInit`, except that the mapped tuple is a triple.\n","type":"(( Emitter.Model appMsg, Platform.Cmd.Cmd (Emitter.Msg appMsg), Platform.Cmd.Cmd appMsg ) -> appMsg) -> Emitter.Program flag appMsg -> flag -> appMsg"},{"name":"mapSubscriptions","comment":" Similarly to `Page.mapSubscriptions`, this function maps over the subscriptions of the `Emitter.Program`.\n","type":"(Emitter.Msg appMsg -> appMsg) -> Emitter.Model appMsg -> Platform.Sub.Sub appMsg"},{"name":"mapView","comment":" Similarly to `Page.mapView`, this function maps over the view of the `Emitter.Program`.\n","type":"(Emitter.Msg appMsg -> appMsg) -> Emitter.Model appMsg -> Html.Html appMsg"},{"name":"update","comment":" Similarly to `Page.updated`, but the returned tuple includes, as its third component, a `Cmd msg` that inserts the emitted `AppMsg` into the main loop of the application.\n","type":"Emitter.Msg appMsg -> Emitter.Model appMsg -> ( Emitter.Model appMsg, Platform.Cmd.Cmd (Emitter.Msg appMsg), Platform.Cmd.Cmd appMsg )"}],"binops":[]},{"name":"Page","comment":" This module allows you to combine multiple apps created with `Browser.element` or `Browser.sandbox` into a single application, with or without URL control. The key feature of the `Program` type is that, unlike other attempts to simplify SPA development, it does not use type variables for inner model and messages (it's `Program flag`, not `Program flag model msg`). This allows you to combine all the pages into a single `List`, `Dict`, `Random.Generator`, or any other data structure you like.\n\nUsers need to write a bit of boilerplate. For example, if you want to use the digital clock application (discussed in the official guide's subscription section), you'll need to set up a corresponding module like this. (This code is based on the one in the official guide, with first line added and `Page` substituted for `Browser` and `program` for `main`.)\n\n    module DigitalClock exposing (program)\n\n    -- Show the current time in your time zone.\n    --\n    -- Read how it works:\n    --   https://guide.elm-lang.org/effects/time.html\n    --\n    -- For an analog clock, check out this SVG example:\n    --   https://elm-lang.org/examples/clock\n    --\n\n    import Html exposing (..)\n    import Page\n    import Task\n    import Time\n\n\n    -- MAIN\n    program =\n        Page.element\n            { init = init\n            , view = view\n            , update = update\n            , subscriptions = subscriptions\n            }\n\n    -- MODEL\n    type alias Model =\n        { zone : Time.Zone\n        , time : Time.Posix\n        }\n\n    init : () -> ( Model, Cmd Msg )\n    init _ =\n        ( Model Time.utc (Time.millisToPosix 0)\n        , Task.perform AdjustTimeZone Time.here\n        )\n\n    -- UPDATE\n    type Msg\n        = Tick Time.Posix\n        | AdjustTimeZone Time.Zone\n\n    update : Msg -> Model -> ( Model, Cmd Msg )\n    update msg model =\n        case msg of\n            Tick newTime ->\n                ( { model | time = newTime }\n                , Cmd.none\n                )\n\n            AdjustTimeZone newZone ->\n                ( { model | zone = newZone }\n                , Cmd.none\n                )\n\n    -- SUBSCRIPTIONS\n    subscriptions : Model -> Sub Msg\n    subscriptions model =\n        Time.every 1000 Tick\n\n    -- VIEW\n    view : Model -> Html Msg\n    view model =\n        let\n            hour =\n                String.fromInt (Time.toHour model.zone model.time)\n\n            minute =\n                String.fromInt (Time.toMinute model.zone model.time)\n\n            second =\n                String.fromInt (Time.toSecond model.zone model.time)\n        in\n        h1 [] [ text (hour ++ \":\" ++ minute ++ \":\" ++ second) ]\n\nYou can use this page module as follows:\n\n    module Main exposing (..)\n\n    import Browser\n    import DigitalClock\n    import Html exposing (..)\n    import Page\n\n    main : Program () Model Msg\n    main =\n        Browser.element\n            { init = init\n            , subscriptions = subscriptions\n            , update = update\n            , view = view\n            }\n\n    type alias Model =\n        { page : Page.Model\n        }\n\n    init : () -> ( Model, Cmd Msg )\n    init _ =\n        update\n            (Page.mapInit PageInitialized DigitalClock.program ())\n            { page = Page.empty }\n\n    subscriptions : Model -> Sub Msg\n    subscriptions model =\n        Page.mapSubscriptions GotPageMsg model.page\n\n    type Msg\n        = PageInitialized ( Page.Model, Cmd Page.Msg )\n        | GotPageMsg Page.Msg\n\n    update : Msg -> Model -> ( Model, Cmd Msg )\n    update msg model =\n        case msg of\n            PageInitialized ( initialPage, initialCmd ) ->\n                ( { model\n                    | page = initialPage\n                  }\n                , Cmd.map GotPageMsg initialCmd\n                )\n\n            GotPageMsg pMsg ->\n                let\n                    ( newPage, newPageCmd ) =\n                        Page.update pMsg model.page\n                in\n                ( { model\n                    | page = newPage\n                  }\n                , Cmd.map GotPageMsg newPageCmd\n                )\n\n    view : Model -> Html Msg\n    view model =\n        Page.mapView GotPageMsg model.page\n\nFor usage with multiple pages, see [the GitHub repository](https://github.com/kudzu-forest/elm-page).\n\n\n# CoreTypes\n\n@docs Model, Msg, Program\n\n\n# Creation\n\n@docs empty, element, sandbox\n\n\n# Usage\n\n@docs mapInit, update, mapView, mapSubscriptions\n\n","unions":[{"name":"Model","comment":" A custom type representing internal states of your page.\n\n  - The `Page.Model` is distinct from the `Model` defined in individual page modules.\n      - `Page.Model` provides a level of abstraction that enables consistent handling of all your pages.\n      - The values stored in your `Model` in each page module cannot be accessed from outside of that page.\n\n","args":[],"cases":[]},{"name":"Msg","comment":" A custom type representing `Msg`s in your page module. You need to use `Page.update` to access this value. See the example above.\n\n  - The `Page.Msg` is distinct from the `Msg` defined in individual page modules.\n      - `Page.Msg` provides a level of abstraction that enables consistent handling of all your pages.\n      - Sending and receiving values across `Page`s are only possible with flags and ports. If your application needs more communication between pages, please take a look at `Emitter` module as well.\n","args":[],"cases":[]},{"name":"Program","comment":" A custom type representing the main program of a page. Values of this type can be passed to the `Page.mapInit` function with a flag.\n","args":["flag"],"cases":[]}],"aliases":[],"values":[{"name":"element","comment":" Functions similarly to `Browser.element`. The return value is wrapped in `Page.Program flag` and can be passed to `Page.mapInit` along with a flag.\n","type":"{ init : flag -> ( model, Platform.Cmd.Cmd msg ), subscriptions : model -> Platform.Sub.Sub msg, update : msg -> model -> ( model, Platform.Cmd.Cmd msg ), view : model -> Html.Html msg } -> Page.Program flag"},{"name":"empty","comment":" An empty page. This can be used for initialization. See example above.\n","type":"Page.Model"},{"name":"mapInit","comment":" The only way you can start new page.\n","type":"(( Page.Model, Platform.Cmd.Cmd Page.Msg ) -> appMsg) -> Page.Program flag -> flag -> appMsg"},{"name":"mapSubscriptions","comment":" Don't forget to use this in your `subscriptions` in the parent module!\n","type":"(Page.Msg -> appMsg) -> Page.Model -> Platform.Sub.Sub appMsg"},{"name":"mapView","comment":" You can use your page with this function. See the example above.\n","type":"(Page.Msg -> appMsg) -> Page.Model -> Html.Html appMsg"},{"name":"sandbox","comment":" Functions similarly to `Browser.sandbox`. You can create a `Page.Program ()` easily by just using `Page.sandbox` instead of `Browser.sandbox`.\n","type":"{ init : model, update : msg -> model -> model, view : model -> Html.Html msg } -> Page.Program ()"},{"name":"update","comment":" The only way to handle `Page.Msg` value from a child component.\n\n- The message will be ignored and nothing happens if following condition is not satisfied.\n    - the `Page.Msg` value as the first argument and the `Page.Model` value as the second argument belongs to __the same page__.\n    - Here, __the same page__ means that they share the initialization `mapInit` function call. (check the `Process.sleep` example in the gitHub repository.)\n    - In order to realize this feature, this module internally depends on [harrysarson/elm-hacky-unique](https://package.elm-lang.org/packages/harrysarson/elm-hacky-unique/1.0.0/).\n","type":"Page.Msg -> Page.Model -> ( Page.Model, Platform.Cmd.Cmd Page.Msg )"}],"binops":[]}]