[{"name":"Yafl","comment":" This library helps you build user input forms in Elm by creating and\ncomposing self-contained [`Widget`](#Widget)s.\n\n\n## Table of contents\n\n\n### [Creating Widgets](#creating-widgets)\n\n[`Widget`](#Widget)\n\n\n### [Turning Widgets into Fields](#turning-widgets-into-fields)\n\n[`Field`](#Field), [`defineFields`](#defineFields), [`addWidget`](#addWidget),\n[`addWidgetWithConfig`](#addWidgetWithConfig), [`endFields`](#endFields)\n\n\n### [Turning Fields into forms](#turning-fields-into-forms)\n\n[`Model`](#Model), [`Msg`](#Msg), [`init`](#init), [`load`](#load),\n[`update`](#update), [`ViewConfig`](#ViewConfig), [`view`](#view),\n[`Wizard`](#Wizard), [`viewWizard`](#viewWizard), [`Feedback`](#Feedback),\n[`subscriptions`](#subscriptions), [`submit`](#submit)\n\n\n### [Combining Fields](#combining-fields)\n\n[`succeed`](#succeed), [`fail`](#fail), [`failAt`](#failAt), [`map`](#map),\n[`andMap`](#andMap), [`andThen`](#andThen), [`choice`](#choice),\n[`option`](#option)\n\n\n### [Customizing Fields](#customizing-fields)\n\n[`label`](#label), [`htmlBefore`](#htmlBefore), [`htmlAfter`](#htmlAfter)\n\n\n### [Validating Fields](#validating-fields)\n\n[`error`](#error), [`errorAt`](#errorAt), [`warning`](#warning), [`warningAt`](#warningAt)\n\n\n### [Communicating between Fields](#communicating-between-fields)\n\n[`HasId`](#HasId), [`NoId`](#NoId), [`identifier`](#identifier),\n[`intercept`](#intercept), [`send`](#send)\n\n\n### [Testing and debugging](#debugging)\n\n[`studio`](#studio), [`toDOT`](#toDOT)\n\n\n# Creating Widgets\n\n[_Back to top_](#table-of-contents)\n\n[`Widget`](#Widget)s are the basic building blocks of this package. Each widget\nis effectively a little Elm application, with its own `init`, `update`, `view`\nand `subscriptions` functions, plus a couple of extra features.\n\nThis package doesn't supply any prebuilt widgets. Every app is unique, and it's\nunlikely that a prebuilt widget would precisely fit your use case. But the point\nis, this package gives you the power to create _any_ types of widgets you\nchoose, and compose them together very easily with minimal boilerplate.\n\nNevertheless, we'll provide some code samples for a few simple widgets that we\ncan use in the code snippets in these docs.\n\n    module Examples exposing (..)\n\n    import Html as H\n    import Html.Attributes as HA\n    import Html.Events as HE\n    import Yafl\n\n    {-| A basic `Widget` that produces a `String`. Its internal\n    `model` and `msg` types are also `String`s.\n    -}\n    stringWidget : Yafl.Widget String String String\n    stringWidget =\n        { init = ( \"\", Cmd.none )\n        , update = \\msg model -> ( msg, Cmd.none )\n        , view =\n            \\{ label, id, feedback } model ->\n                [ H.label [ HA.for id ] [ H.text label ]\n                , H.input\n                    [ HA.id id\n                    , HA.type_ \"text\"\n                    , HA.value model\n                    , HE.onInput identity\n                    ]\n                    []\n                , H.ul [] (List.map (\\f -> H.li [] [ H.text f ]) feedback)\n                ]\n        , subscriptions = \\model -> Sub.none\n        , submit = \\model -> Ok model\n        , label = \"String\"\n        }\n\n    {-| A `Widget` that produces an `Int`, based on the counter\n    example from the Elm Guide. Its internal `model` type is an\n    `Int`, but its `msg` type is a custom type.\n    -}\n    type CounterMsg\n        = Increment\n        | Decrement\n\n    counterWidget : Yafl.Widget () Int CounterMsg Int\n    counterWidget () =\n        { init = ( 0, Cmd.none )\n        , update =\n            \\msg model ->\n                case msg of\n                    Increment ->\n                        ( model + 1, Cmd.none )\n\n                    Decrement ->\n                        ( model - 1, Cmd.none )\n        , view =\n            \\{ label, id } model ->\n                [ H.label [ HA.for id ] [ H.text label ]\n                , H.fieldset\n                    [ HA.id id ]\n                    [ H.button [ HA.type_ \"button\", HE.onClick Decrement ] [ H.text \"-\" ]\n                    , H.output [] [ H.text (String.fromInt model) ]\n                    , H.button [ HA.type_ \"button\", HE.onClick Increment ] [ H.text \"+\" ]\n                    ]\n                ]\n        , subscriptions = \\_ -> Sub.none\n        , submit = \\model -> Ok model\n        , label = \"Counter\"\n        }\n\n@docs Widget\n\n\n# Turning Widgets into Fields\n\n[_Back to top_](#table-of-contents)\n\nBefore we can use our [`Widget`](#Widget)s to create a form, we need to convert them into\n[`Field`](#Field)s. This conversion process effectively combines the internal `model` and\n`msg` types of each widget to create composite types that we can use as the\ntop-level `model` and `msg` for the entire form.\n\nWe perform this conversion using three functions: [`defineFields`](#defineFields), [`addWidget`](#addWidget),\nand [`endFields`](#endFields). The type signatures for these three functions are extremely\nterrifying, but fortunately we don't need to understand them - just follow the\nexample below:\n\n    module Examples exposing (Model, Msg, fields)\n\n    import Yafl exposing (addWidget, defineFields, endFields)\n\n    fields =\n        Yafl.defineFields\n            (\\string counter -> { string = string, counter = counter })\n            |> Yafl.addWidget stringWidget\n            |> Yafl.addWidget counterWidget\n            |> Yafl.endFields\n\n    {- This gives us the following Model and Msg types for\n       our form:\n    -}\n    type alias FormModel =\n        ( Maybe String, ( Maybe Int, () ) )\n\n    type alias FormMsg =\n        ( Maybe String, ( Maybe CounterMsg, () ) )\n\n@docs Field, defineFields, addWidget, addWidgetWithConfig, endFields\n\n\n# Turning Fields into forms\n\nOnce we've defined our [`Field`](#Field)s, we can start the fun part: making forms!\n\nImagine we just want a simple form that allows a user to choose an `Int`:\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n    import Html exposing (Html)\n\n    -- We can turn any Field into a form:\n\n    form =\n        fields.counter\n\n    -- Initialize it with `Yafl.init` to get a (model, cmd)\n    -- tuple:\n\n    init =\n        Yafl.init form\n\n    init\n\n    --: ( Yafl.Model FormModel Int, Cmd (Yafl.Msg FormMsg) )\n\n    -- The form's model can then be passed to `Yafl.view`,\n    -- `Yafl.update`, `Yafl.subscriptions` and `Yafl.submit`:\n\n    model =\n        Tuple.first init\n\n    Yafl.view form model\n\n    --: List (Html (Yafl.Msg FormMsg))\n\n    Yafl.subscriptions form model\n\n    --: Sub (Yafl.Msg FormMsg)\n\n    Yafl.submit form model\n\n    --> Ok 0\n\n@docs Model, Msg, init, load, update, ViewConfig, view, Wizard, viewWizard, Feedback, subscriptions, submit\n\n\n# Combining Fields\n\n[_Back to top_](#table-of-contents)\n\n\n## Succeeding and failing\n\nIn addition to the [`Field`](#Field)s that you define based on your\n[`Widget`](#Widget)s, the package also provides [`succeed`](#succeed) and\n[`fail`](#fail), which can be useful in various ways when\nused with other combinators such as [`andMap`](#andMap). You may be familiar with similar functions from packages\nsuch as [`elm/json`](http://package.elm-lang.org/packages/elm/json/latest/Json-Decode#succeed).\n\nThe views of these fields return an empty Html element. When\nsubmitted, `succeed` always returns an `Ok`, while `fail` always returns an\n`Err`.\n\n@docs succeed, fail, failAt\n\n\n## Converting input and output types\n\n@docs map, contraMap\n\n\n## Building product types\n\n@docs andMap, andThen\n\n\n## Building custom types\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    type MyCustomType\n        = Foo String\n        | Bar Int\n\n    myCustomTypeField =\n        Yafl.choice\n            |> Yafl.option \"Foo\" .foo fooField\n            |> Yafl.option \"Bar\" .bar barField\n\n    fooField =\n        fields.string\n            |> Yafl.map Foo\n\n    barField =\n        fields.counter\n            |> Yafl.map Bar\n\n    model =\n        myCustomTypeField\n            |> Yafl.init\n            |> Tuple.first\n\n    Yafl.submit myCustomTypeField model\n\n    --> Ok (Foo \"\")\n\n@docs choice, option\n\n\n# Customizing Fields\n\n[_Back to top_](#table-of-contents)\n\n@docs label, htmlBefore, htmlAfter\n\n\n# Validating fields\n\n[_Back to top_](#table-of-contents)\n\n@docs error, errorAt, warning, warningAt\n\n\n# Communicating between Fields\n\n[_Back to top_](#table-of-contents)\n\n@docs HasId, NoId, identifier, intercept, send, isFormValid\n\n\n# Debugging\n\n[_Back to top_](#table-of-contents)\n\n@docs studio, toDOT\n\n","unions":[{"name":"Field","comment":" Forms are composed of `Field`s - this is the main data type we'll be using in this package.\n","args":["formModel","formMsg","id","widgetMsg","input","output"],"cases":[]},{"name":"HasId","comment":" Indicates that a [`Field`](#Field) has been given an `identifier`, and can therefore be\nused with [`intercept`](#intercept), [`send`](#send), etc. See the docs for [`identifier`](#identifier).\n","args":[],"cases":[]},{"name":"Model","comment":" The top-level model type for your form.\n","args":["formModel","output"],"cases":[]},{"name":"Msg","comment":" The top-level message type for your form.\n","args":["formMsg"],"cases":[]},{"name":"NoId","comment":" Indicates that a [`Field`](#Field) has not been given an `identifier`. See the docs for\n[`identifier`](#identifier).\n","args":[],"cases":[]}],"aliases":[{"name":"Feedback","comment":" Feedback produced when the [`submit`](#submit) function on a [`Field`](#Field) returns errors.\n","args":[],"type":"{ isError : Basics.Bool, message : String.String }"},{"name":"ViewConfig","comment":" Configuration passed into the view of each [`Field`](#Field) in your form.\n","args":[],"type":"{ label : String.String, id : String.String, feedback : List.List Yafl.Feedback }"},{"name":"Widget","comment":" The `Widget` type is very similar to the record type that you would supply\nto [`Browser.element`](http://package.elm-lang.org/packages/elm/browser/latest/Browser#element) to create\nan Elm [`Program`](http://package.elm-lang.org/packages/elm/core/latest/Platform#Program).\n","args":["config","model","msg","output"],"type":"config -> Yafl.InnerWidget model msg output"},{"name":"Wizard","comment":" A record produced by [`viewWizard`](#viewWizard), containing fields that are\nuseful if you want to render your form as a multi-step \"wizard\".\n\n  - `stepView` is the HTML produced by the view function for the current step of\n    the wizard.\n\n  - `stepIndex` is the zero-indexed number of the current step of the wizard.\n\n  - `totalSteps` is the total number of steps in the wizard.\n\n  - `selectStepMsg` lets you jump to a specified step of the wizard - for\n    example, `selectStepMsg (currentStep + 1)` would move to the next step of\n    the wizard. (In general, you'll want to take care not to let the user move\n    to a `stepIndex` less than 0 or greater than `totalSteps - 1`, but there\n    _are_ possible designs where you might want to do this, so Yafl doesn't\n    guard against it.)\n\n  - `isStepValid` indicates whether all the fields displayed in the current step\n    of the wizard pass validation (i.e. their `submit` functions return an\n    `Ok`). You could use this to decide whether to display a \"next\" button in\n    the view of the current step.\n\n","args":["formMsg"],"type":"{ stepView : List.List (Html.Html (Yafl.Msg formMsg)), stepIndex : Basics.Int, totalSteps : Basics.Int, selectStepMsg : Basics.Int -> Yafl.Msg formMsg, isStepValid : Basics.Bool }"}],"values":[{"name":"addWidget","comment":" Add a Widget to the definition of the Fields you want to use in your forms.\n","type":"Yafl.Widget () widgetModel widgetMsg output -> { apply : ({ blankModel : formModel, blankMsg : formMsg, ctor : Yafl.Field formModel formMsg Yafl.NoId widgetMsg widgetMsg output -> fields } -> ( formMsg -> Maybe.Maybe widgetMsg, previousMsgGetters ) -> ( Maybe.Maybe widgetMsg -> formMsg -> formMsg, previousMsgSetters ) -> ( formModel -> Maybe.Maybe widgetModel, previousModelGetters ) -> ( Maybe.Maybe widgetModel -> formModel -> formModel, previousModelSetters ) -> ( Yafl.InnerWidget widgetModel widgetMsg output, previousWidgets ) -> accForNext) -> toFolder5, ctor : f, widgets : ( Yafl.InnerWidget widgetModel widgetMsg output, previousWidgets ) -> toWidgets, modelBlanks : ( Maybe.Maybe widgetModel, previousBlankModels ) -> toBlankModel, modelGetters : { appendToGetters : ( tuple3 -> head3, nextModelGetters ) -> toModelGetters, focus : tuple3 -> ( head3, tail4 ) }, modelSetters : { appendToSetters : ( head2 -> tuple2 -> tuple2, nextModelSetters ) -> toModelSetters, focus : (( head2, tail3 ) -> ( head2, tail3 )) -> tuple2 -> tuple2 }, msgBlanks : ( Maybe.Maybe widgetMsg, previousBlankMsgs ) -> toBlankMsg, msgGetters : { appendToGetters : ( tuple1 -> head1, nextMsgGetters ) -> toMsgGetters, focus : tuple1 -> ( head1, tail1 ) }, msgSetters : { appendToSetters : ( head -> tuple -> tuple, nextMsgSetters ) -> toMsgSetters, focus : (( head, tail ) -> ( head, tail )) -> tuple -> tuple } } -> { apply : ({ blankModel : formModel, blankMsg : formMsg, ctor : fields } -> previousMsgGetters -> previousMsgSetters -> previousModelGetters -> previousModelSetters -> previousWidgets -> accForNext) -> toFolder5, ctor : f, widgets : previousWidgets -> toWidgets, modelBlanks : previousBlankModels -> toBlankModel, modelGetters : { appendToGetters : nextModelGetters -> toModelGetters, focus : tuple3 -> tail4 }, modelSetters : { appendToSetters : nextModelSetters -> toModelSetters, focus : (tail3 -> tail3) -> tuple2 -> tuple2 }, msgBlanks : previousBlankMsgs -> toBlankMsg, msgGetters : { appendToGetters : nextMsgGetters -> toMsgGetters, focus : tuple1 -> tail1 }, msgSetters : { appendToSetters : nextMsgSetters -> toMsgSetters, focus : (tail -> tail) -> tuple -> tuple } }"},{"name":"addWidgetWithConfig","comment":" Add a configurable Widget to the definition of the Fields you want to use in\nyour forms. Each time you use a Field derived from this Widget in your form, you\nwill be able to pass in a `config` value.\n","type":"Yafl.Widget config widgetModel widgetMsg output -> { apply : ({ blankModel : formModel, blankMsg : formMsg, ctor : (config -> Yafl.Field formModel formMsg Yafl.NoId widgetMsg widgetMsg output) -> fields } -> ( formMsg -> Maybe.Maybe widgetMsg, previousMsgGetters ) -> ( Maybe.Maybe widgetMsg -> formMsg -> formMsg, previousMsgSetters ) -> ( formModel -> Maybe.Maybe widgetModel, previousModelGetters ) -> ( Maybe.Maybe widgetModel -> formModel -> formModel, previousModelSetters ) -> ( Yafl.Widget config widgetModel widgetMsg output, previousWidgets ) -> accForNext) -> toFolder5, ctor : f, widgets : ( Yafl.Widget config widgetModel widgetMsg output, previousWidgets ) -> toWidgets, modelBlanks : ( Maybe.Maybe widgetModel, previousBlankModels ) -> toBlankModel, modelGetters : { appendToGetters : ( tuple3 -> head3, nextModelGetters ) -> toModelGetters, focus : tuple3 -> ( head3, tail4 ) }, modelSetters : { appendToSetters : ( head2 -> tuple2 -> tuple2, nextModelSetters ) -> toModelSetters, focus : (( head2, tail3 ) -> ( head2, tail3 )) -> tuple2 -> tuple2 }, msgBlanks : ( Maybe.Maybe widgetMsg, previousBlankMsgs ) -> toBlankMsg, msgGetters : { appendToGetters : ( tuple1 -> head1, nextMsgGetters ) -> toMsgGetters, focus : tuple1 -> ( head1, tail1 ) }, msgSetters : { appendToSetters : ( head -> tuple -> tuple, nextMsgSetters ) -> toMsgSetters, focus : (( head, tail ) -> ( head, tail )) -> tuple -> tuple } } -> { apply : ({ blankModel : formModel, blankMsg : formMsg, ctor : fields } -> previousMsgGetters -> previousMsgSetters -> previousModelGetters -> previousModelSetters -> previousWidgets -> accForNext) -> toFolder5, ctor : f, widgets : previousWidgets -> toWidgets, modelBlanks : previousBlankModels -> toBlankModel, modelGetters : { appendToGetters : nextModelGetters -> toModelGetters, focus : tuple3 -> tail4 }, modelSetters : { appendToSetters : nextModelSetters -> toModelSetters, focus : (tail3 -> tail3) -> tuple2 -> tuple2 }, msgBlanks : previousBlankMsgs -> toBlankMsg, msgGetters : { appendToGetters : nextMsgGetters -> toMsgGetters, focus : tuple1 -> tail1 }, msgSetters : { appendToSetters : nextMsgSetters -> toMsgSetters, focus : (tail -> tail) -> tuple -> tuple } }"},{"name":"andMap","comment":" Combine multiple fields. Use in combination with [`succeed`](#succeed).\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    form =\n        Yafl.succeed (\\a b c -> { firstName = a, middleName = b, lastName = c })\n            |> Yafl.andMap .firstName (fields.string |> Yafl.label \"First name\")\n            |> Yafl.andMap .middleName (fields.string |> Yafl.label \"Middle name\")\n            |> Yafl.andMap .lastName (fields.string |> Yafl.label \"Last name\")\n\n    model =\n        Yafl.init form\n            |> Tuple.first\n\n    Yafl.submit form model\n    --> Ok { firstName = \"\", middleName = \"\", lastName = \"\" }\n\n","type":"(options -> Maybe.Maybe input) -> Yafl.Field formModel formMsg id widgetMsg input output1 -> Yafl.Field formModel formMsg Basics.Never Basics.Never options (output1 -> output2) -> Yafl.Field formModel formMsg Basics.Never Basics.Never options output2"},{"name":"andThen","comment":" Check the result of submitting a [`Field`](#Field). This can be useful if\nyou want to convert an existing [`Widget`](#Widget) to return a different output\ntype.\n\n(You _can_ also use it for validating a field's output, but it will probably be\nbetter to use [`error`](#error) or [`errorAt`](#errorAt) instead.)\n\nBe warned: this is not a fully law-abiding monadic `andThen` - you shouldn't use\nit to return arbitrary Fields, you should only use it with `succeed`, `fail` and\n`failAt`\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    -- Example 1: Repurposing an existing widget to return\n    -- a different type\n\n    fields.string\n            |> Yafl.label \"Enter a floating-point number\"\n            |> Yafl.andThen\n                (\\string ->\n                    case String.toFloat string of\n                        Just float ->\n                            Yafl.succeed float\n\n                        Nothing ->\n                            Yafl.fail\n                                \"That's not a valid float\"\n                )\n\n    --: Yafl.Field FormModel FormMsg Yafl.NoId String String Float\n\n    -- Example 2: Validating a field's output\n    -- (This works, but it's better to use `error`\n    -- and `errorAt`.)\n\n    fields.string\n        |> Yafl.label \"Enter the first name of a Beatle\"\n        |> Yafl.andThen\n            (\\name ->\n                if List.member name\n                    [ \"John\", \"Paul\", \"George\", \"Ringo\" ]\n                then\n                    Yafl.succeed name\n\n                else\n                    Yafl.fail \"Invalid Beatle\"\n            )\n\n    --: Yafl.Field FormModel FormMsg Yafl.NoId String String String\n\n","type":"(output -> Yafl.Field formModel formMsg Basics.Never Basics.Never input output2) -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input output2"},{"name":"choice","comment":" Begin defining a `choice` between multiple [`option`](#option)s.\n\nThis doesn't do anything useful on its own - it needs to be used in conjunction\nwith `option`\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    Yafl.choice\n\n    --: Yafl.Field FormModel FormMsg Never Never { selected : Maybe Int, options : Maybe {} } Int\n\n","type":"Yafl.Field model formMsg Basics.Never Basics.Never { selected : Maybe.Maybe Basics.Int, options : Maybe.Maybe options } value"},{"name":"contraMap","comment":" Convert the input of a [`Field`](#Field) from one type to another.\n\nThis is useful if you want to control how data is loaded into your form with\n[`load`](#load).\n\n    import Examples exposing (FormModel, FormMsg, fields)\n    import Yafl\n\n    passwordField :\n        Yafl.Field\n            FormModel\n            FormMsg\n            Never\n            Never\n            -- Here's the `input` parameter:\n            { password : Maybe String\n            , confirm : Maybe String\n            }\n            String\n    passwordField =\n        Yafl.succeed\n            (\\p c -> { password = p, confirm = c })\n            |> Yafl.andMap .password fields.string\n            |> Yafl.andMap .confirm fields.string\n            |> Yafl.error\n                (\\{ password, confirm } ->\n                    if password == confirm then\n                        Nothing\n\n                    else\n                        Just \"Passwords need to match\"\n                )\n            |> Yafl.map .password\n\n    -- With the `.password` and `.confirm` functions that we\n    -- pass to `andMap` here, our `Field`'s `input` type\n    -- parameter is a record containing both of those fields.\n    -- By using `contraMap`, we can change the `input` type\n    -- to make the field a bit easier to use.\n\n    passwordFieldThatIsEasierToLoad :\n        Yafl.Field\n            FormModel\n            FormMsg\n            Never\n            Never\n            -- after `contraMap`, the `input` parameter\n            -- is just a `String`\n            String\n            String\n    passwordFieldThatIsEasierToLoad =\n        passwordField\n            |> Yafl.contraMap\n                (\\string ->\n                    { password = Just string\n                    , confirm = Just string\n                    }\n                )\n\n    -- DOC TESTS\n    passwordField --: Yafl.Field FormModel FormMsg Never Never { password : Maybe String, confirm : Maybe String } String\n    passwordFieldThatIsEasierToLoad --: Yafl.Field FormModel FormMsg Never Never String String\n\n","type":"(input2 -> input) -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input2 output"},{"name":"defineFields","comment":" Begin a definition of the fields you want to use in your forms.\n","type":"ctor -> { ctor : ctor, widgets : b -> b, modelGetters : { focus : focus -> focus, appendToGetters : getters -> getters }, modelSetters : { focus : c -> c, appendToSetters : setters -> setters }, modelBlanks : d -> d, msgGetters : { focus : e -> e, appendToGetters : f -> f }, msgSetters : { focus : g -> g, appendToSetters : h -> h }, msgBlanks : i -> i, apply : j -> j }"},{"name":"endFields","comment":" Finalize the definition of the Fields you want to use in your forms.\n","type":"{ apply : (acc -> empty -> empty -> empty -> empty -> empty -> acc) -> { blankModel : modelBlanks, blankMsg : msgBlanks, ctor : toFields } -> msgGetters -> msgSetters -> modelGetters -> modelSetters -> widgets -> { blankModel : modelBlanks, blankMsg : msgBlanks, ctor : fields }, ctor : toFields, widgets : () -> widgets, modelBlanks : () -> modelBlanks, modelGetters : { appendToGetters : () -> modelGetters, focus : focus3 }, modelSetters : { appendToSetters : () -> modelSetters, focus : focus2 }, msgBlanks : () -> msgBlanks, msgGetters : { appendToGetters : () -> msgGetters, focus : focus1 }, msgSetters : { appendToSetters : () -> msgSetters, focus : focus } } -> fields"},{"name":"error","comment":" Validate a `Field` and specify an error message if validation fails.\n\n    import Yafl\n\n    form =\n        Yafl.succeed 0\n            |> Yafl.error\n                (\\int ->\n                    if int > 0 then\n                        Nothing\n                    else\n                        Just\n                            (\"Must be greater than 0, but the value is \"\n                                ++ String.fromInt int\n                            )\n                )\n\n    form\n        |> Yafl.init\n        |> Tuple.first\n        |> Yafl.submit form\n\n    --> Err [ ( \"0\", \"Must be greater than 0, but the value is 0\" ) ]\n\n","type":"(output -> Maybe.Maybe String.String) -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input output"},{"name":"errorAt","comment":" Validate a `Field` and specify an error to display on a _different_ field.\nThis is useful when you are doing validation that involves multiple fields, but\nyou only want to display an error on one field.\n\n    import Yafl\n    import Examples exposing (fields)\n\n    passwordField =\n        fields.string\n            |> Yafl.identifier \"password\"\n\n    confirmField =\n        fields.string\n            |> Yafl.identifier \"confirm\"\n\n    form =\n        Yafl.succeed\n            (\\password confirm -> { password = password, confirm = confirm })\n            |> Yafl.andMap .passwordField passwordField\n            |> Yafl.andMap .confirmField confirmField\n            |> Yafl.errorAt confirmField\n                (\\{ password, confirm } ->\n                    if password == confirm then\n                        Nothing\n                    else\n                        Just \"Passwords do not match\"\n                )\n\n    form\n        |> Yafl.init\n        |> Tuple.first\n        |> Yafl.load form\n            { passwordField = Just \"password123\"\n            , confirmField = Just \"password124\"\n            }\n        |> Tuple.first\n        |> Yafl.submit form\n\n    --> Err [ ( \"confirm\", \"Passwords do not match\" ) ]\n\n","type":"Yafl.Field formModel formMsg Yafl.HasId widgetMsg2 input2 output2 -> (output -> Maybe.Maybe String.String) -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input output"},{"name":"fail","comment":" A Field that always fails on submission with the error message that you supply.\n\n    import Yafl\n\n    form =\n        Yafl.fail \"Oh dear!\"\n\n    model =\n        form\n            |> Yafl.init\n            |> Tuple.first\n\n    Yafl.submit form model\n\n    --> Err [ (\"0\", \"Oh dear!\") ]\n\n","type":"String.String -> Yafl.Field formModel formMsg Basics.Never Basics.Never input output"},{"name":"failAt","comment":" Like `fail`, except it will display the error message on a _different_\nField. This can be useful in multi-field validation, when you have an error that\nresults from a combination of several fields, but you only want to display the\nerror message on one specific field.\n\n    import Examples exposing (fields)\n    import Yafl\n\n    form =\n        Yafl.succeed\n            (\\targetOutput failAtOutput -> targetOutput)\n            |> Yafl.andMap .target targetField\n            |> Yafl.andMap .failure failAtField\n\n    targetField =\n        fields.string\n            |> Yafl.identifier \"target-field\"\n\n    failAtField =\n        Yafl.failAt targetField \"Uh oh!\"\n\n    output =\n        Yafl.init form\n            |> Tuple.first\n            |> Yafl.submit form\n\n    -- The error is assigned to `targetField`,\n    -- not `failAtField`\n    output --> Err [ ( \"target-field\", \"Uh oh!\" ) ]\n\n","type":"Yafl.Field formModel formMsg Yafl.HasId widgetMsg1 input1 output1 -> String.String -> Yafl.Field formModel formMsg Basics.Never Basics.Never input2 output2"},{"name":"htmlAfter","comment":" Add some arbitrary HTML after the view of a field.\n\n    import Examples exposing (FormModel, FormMsg, fields)\n    import Html\n    import Yafl\n\n    form =\n        fields.string\n            |> Yafl.htmlAfter (Html.text \"Here's some text\")\n\n    form --: Yafl.Field FormModel FormMsg Yafl.NoId String String String\n\n","type":"Html.Html Basics.Never -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input output"},{"name":"htmlBefore","comment":" Add some arbitrary HTML before the view of a field.\n\n    import Examples exposing (FormModel, FormMsg, fields)\n    import Html\n    import Yafl\n\n    form =\n        fields.string\n            |> Yafl.htmlBefore (Html.text \"Here's some text\")\n\n    form --: Yafl.Field FormModel FormMsg Yafl.NoId String String String\n\n","type":"Html.Html Basics.Never -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input output"},{"name":"identifier","comment":" Add a unique identifier to a [`Field`](#Field), which can be used to send and intercept\nmessages to that Field.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    myField =\n        fields.string\n\n    myField\n\n    --: Yafl.Field FormModel FormMsg Yafl.NoId String String String\n\n    myFieldWithId =\n        myField\n            |> Yafl.identifier \"any-string-as-long-as-it's-unique\"\n\n    myFieldWithId\n\n    --: Yafl.Field FormModel FormMsg Yafl.HasId String String String\n\n    Yafl.send myFieldWithId \"Hello!\"\n\n    --: Cmd (Yafl.Msg FormMsg)\n\nThis identifier is also used as the `id` string in [`ViewConfig`](#ViewConfig),\nwhich is passed into the view when the Field is rendered. When defining a\nWidget, you can use the `id` field of the `ViewConfig` to set the\n`Html.Attributes.id` of the HTML input.\n\n","type":"String.String -> Yafl.Field formModel formMsg Yafl.NoId widgetMsg input output -> Yafl.Field formModel formMsg Yafl.HasId widgetMsg input output"},{"name":"init","comment":" Initialize your form\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    fields.counter\n        |> Yafl.init\n\n    --: ( Yafl.Model FormModel Int, Cmd (Yafl.Msg FormMsg) )\n\n","type":"Yafl.Field formModel formMsg id widgetMsg input output -> ( Yafl.Model formModel output, Platform.Cmd.Cmd (Yafl.Msg formMsg) )"},{"name":"intercept","comment":" Intercept the top-level `Msg` sent to your form, and if it contains a message sent to the specified field, return that message.\n\n    import Yafl\n    import Examples exposing (CounterMsg, FormModel, FormMsg, fields)\n\n    myFieldWithId =\n        fields.counter\n            |> Yafl.identifier \"any-string-as-long-as-it's-unique\"\n\n    model =\n        Yafl.init myFieldWithId\n            |> Tuple.first\n\n    Yafl.intercept myFieldWithId model\n\n    --: Yafl.Msg FormMsg -> Maybe CounterMsg\n\n","type":"Yafl.Field formModel formMsg Yafl.HasId widgetMsg input fieldOutput -> Yafl.Model formModel formOutput -> Yafl.Msg formMsg -> Maybe.Maybe widgetMsg"},{"name":"isFormValid","comment":" Check that a form doesn't contain fields with duplicate identifiers.\n","type":"Yafl.Field formModel formMsg id widgetMsg input output -> Basics.Bool"},{"name":"label","comment":" Add a label to a Field.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n\n    fields.string\n        |> Yafl.label \"What is your name?\"\n\n    --: Yafl.Field FormModel FormMsg Yafl.NoId String String String\n\n","type":"String.String -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input output"},{"name":"load","comment":" Load data into your form. A bit tricky to explain, but see the examples\nbelow:\n\nFor simple `Field`s, you just pass a value of the underlying `Widget`'s `msg`\ntype. This will dispatch the `msg` to the `Field`'s update function, which may\nthen update its model and optionally send a `Cmd`.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, CounterMsg(..), fields)\n\n    form =\n        fields.counter\n\n    modelBeforeLoading =\n        form\n            |> Yafl.init\n            |> Tuple.first\n\n    Yafl.submit form modelBeforeLoading\n    --> Ok 0\n\n    modelAfterLoading =\n        modelBeforeLoading\n            |> Yafl.load form Increment\n            |> Tuple.first\n\n    Yafl.submit form modelAfterLoading\n    --> Ok 1\n\nFor `Field`s composed using `andMap`, you can pass in a record where each field\nis a `Maybe widgetMsg`. If the record field's value is `Just`, then the message\nwill be dispatched to the `Field`'s update function. If it's `Nothing`, then no\nmessage will be dispatched and the `Field`'s model will remain unchanged.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, CounterMsg(..), fields)\n\n    form =\n        Yafl.succeed (\\int string -> ( int, string ))\n            |> Yafl.andMap .a fields.counter\n            |> Yafl.andMap .b fields.string\n\n    form\n    --: Yafl.Field FormModel FormMsg Never Never { a : Maybe CounterMsg, b : Maybe String } ( Int, String )\n\n    modelBeforeLoading =\n        form\n            |> Yafl.init\n            |> Tuple.first\n\n    Yafl.submit form modelBeforeLoading\n    --> Ok (0, \"\")\n\n    modelAfterLoading =\n        modelBeforeLoading\n            |> Yafl.load form\n                { a = Nothing\n                , b = Just \"hello\"\n                }\n            |> Tuple.first\n\n    Yafl.submit form modelAfterLoading\n    --> Ok ( 0, \"hello\" )\n\nFor `Field`s composed using `choice` and `option`, it's a similar story, except\nthat the options are nested within a record of the form `{ selected : Maybe Int,\noptions : {...} }`. The `selected` field is used to pick which of the options\nshould be selected (it's zero-indexed, so 0 is the first option, 1 is the\nsecond, etc.)\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, CounterMsg(..), fields)\n\n    type Foo\n        = Bar Int\n        | Qux String\n\n    form =\n        Yafl.choice\n            |> Yafl.option \"Bar\" .bar barField\n            |> Yafl.option \"Qux\" .qux quxField\n\n    barField =\n        Yafl.map Bar fields.counter\n\n    quxField =\n        Yafl.map Qux fields.string\n\n    form\n    --: Yafl.Field FormModel FormMsg Never Never { selected : Maybe Int, options : Maybe { bar : Maybe CounterMsg, qux : Maybe String } } Foo\n\n    modelBeforeLoading =\n        form\n            |> Yafl.init\n            |> Tuple.first\n\n    Yafl.submit form modelBeforeLoading\n    --> Ok (Bar 0)\n\n    modelAfterLoading =\n        modelBeforeLoading\n            |> Yafl.load form\n                { selected = Just 1\n                , options =\n                    Just\n                        { bar = Nothing\n                        , qux = Just \"hello\"\n                        }\n                }\n            |> Tuple.first\n\n    Yafl.submit form modelAfterLoading\n    --> Ok (Qux \"hello\")\n\n","type":"Yafl.Field formModel formMsg id widgetMsg input output -> input -> Yafl.Model formModel output -> ( Yafl.Model formModel output, Platform.Cmd.Cmd (Yafl.Msg formMsg) )"},{"name":"map","comment":" Convert the output of a [`Field`](#Field) from one type to another.\n\nA common use case for this function is to create `Field`s that produce custom\ntype variants.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    -- Example: Creating a custom type variant\n\n    type MyCustomType\n        = Foo String\n\n    fooField =\n        Yafl.map Foo (fields.string)\n\n    fooField\n        |> Yafl.init\n        |> Tuple.first\n        |> Yafl.submit fooField\n\n    --> Ok (Foo \"\")\n\n","type":"(output -> output2) -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input output2"},{"name":"option","comment":" Add an option to a [`choice`](#choice).\n\nThe option will render as an HTML radio input in the view, so you need to\nprovide a `String` to serve as a label, plus a `Field` that returns the actual\ntype you want as output.\n\nAll the `options` of a given `choice` must return the same output type,\nalthough their internal `model` and `msg` types can be different.\n\nIf the user selects the radio button for this `option`, then the `Field`'s view\nwill be rendered underneath the fieldset containing the radio buttons.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    Yafl.choice\n        |> Yafl.option\n            \"This is the label for the radio button\"\n            .counter\n            (fields.counter\n                |> Yafl.label \"This is a label for the `counter` field\"\n            )\n\n    --: Yafl.Field FormModel FormMsg Never Never { options : Maybe { counter : Maybe Examples.CounterMsg }, selected : Maybe Int } Int\n\n","type":"String.String -> (options -> Maybe.Maybe input) -> Yafl.Field formModel formMsg id widgetMsg input value -> Yafl.Field formModel formMsg Basics.Never Basics.Never { selected : Maybe.Maybe Basics.Int, options : Maybe.Maybe options } value -> Yafl.Field formModel formMsg Basics.Never Basics.Never { selected : Maybe.Maybe Basics.Int, options : Maybe.Maybe options } value"},{"name":"send","comment":" Create a `Cmd` that will send a message to a specific [`option`](#option) in\na [`choice`](#choice) Field.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    myFieldWithId =\n        fields.string\n            |> Yafl.identifier \"any-string-as-long-as-it's-unique\"\n\n    Yafl.send myFieldWithId \"Hello!\"\n\n    --: Cmd (Yafl.Msg FormMsg)\n\n","type":"Yafl.Field formModel formMsg Yafl.HasId widgetMsg input output -> widgetMsg -> Platform.Cmd.Cmd (Yafl.Msg formMsg)"},{"name":"studio","comment":" Turn a [`Field`](#Field) into an Elm `Program` that you can view in your\nbrowser with in `elm reactor` for testing purposes.\n\nThis should only be used in development - to help you avoid accidentally\ndeploying it in production, you should pass in `Debug.toString` as the first\nargument.\n\n","type":"(output -> String.String) -> Yafl.Field formModel formMsg id widgetMsg input output -> Platform.Program () (Yafl.Model formModel output) (Yafl.Msg formMsg)"},{"name":"submit","comment":" Submit your form.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    form =\n        fields.string\n\n    model =\n        form\n            |> Yafl.init\n            |> Tuple.first\n\n    Yafl.submit form model\n\n    --> Ok \"\"\n\n","type":"Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Model formModel output -> Result.Result (List.List ( String.String, String.String )) output"},{"name":"subscriptions","comment":" Generate subscriptions for your form.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n\n    form =\n        fields.string\n\n    model =\n        form\n            |> Yafl.init\n            |> Tuple.first\n\n    Yafl.subscriptions form model\n\n    --: Sub (Yafl.Msg FormMsg)\n\n","type":"Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Model formModel output -> Platform.Sub.Sub (Yafl.Msg formMsg)"},{"name":"succeed","comment":" A Field that always successfully generates the value that you supply.\n\n    import Yafl\n\n    form =\n        Yafl.succeed \"Hurrah!\"\n\n    model =\n        form\n            |> Yafl.init\n            |> Tuple.first\n\n    Yafl.submit form model\n\n    --> Ok \"Hurrah!\"\n\n","type":"output -> Yafl.Field formModel formMsg Basics.Never Basics.Never input output"},{"name":"toDOT","comment":" Convert a `Model` value into a Graphviz DOT String, which you can visualize\nusing a tool such as <https://dreampuf.github.io/GraphvizOnline>\n\nAs the first argument, you should pass in `Debug.toString`.\n\n","type":"(model -> String.String) -> Yafl.Model model output -> String.String"},{"name":"update","comment":" Update your form by supplying a `Msg` and `Model`\n","type":"Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Msg formMsg -> Yafl.Model formModel output -> ( Yafl.Model formModel output, Platform.Cmd.Cmd (Yafl.Msg formMsg) )"},{"name":"view","comment":" View your form.\n\n    import Yafl\n    import Examples exposing (FormModel, FormMsg, fields)\n    import Html exposing (Html)\n\n    form =\n        fields.string\n\n    model =\n        form\n            |> Yafl.init\n            |> Tuple.first\n\n    Yafl.view form model\n\n    --: List (Html (Yafl.Msg FormMsg))\n\n","type":"Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Model formModel output -> List.List (Html.Html (Yafl.Msg formMsg))"},{"name":"viewWizard","comment":" View your form as a multi-step wizard. This will only work if the top-level\nfield of your form is a product type created with `succeed` and `andMap`.\n\n`viewWizard` doesn't produce a fully-fledged wizard view; it returns a value of\ntype `Wizard`. [Jump over to the `Wizard` docs for an explanation](#Wizard).\n\n","type":"Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Model formModel output -> Yafl.Wizard formMsg"},{"name":"warning","comment":" Validate a `Field` and specify a warning message if validation fails. A\n`warning` is like an `error`, but if you call `submit` on the `Field`, it will\nreturn `Ok`.\n\n    import Yafl\n\n    form =\n        Yafl.succeed 0\n            |> Yafl.warning\n                (\\int ->\n                    if int > 0 then\n                        Nothing\n                    else\n                        Just\n                            (\"Should be greater than 0, but the value is \"\n                                ++ String.fromInt int\n                            )\n                )\n\n    form\n        |> Yafl.init\n        |> Tuple.first\n        --  since we used `warning` instead of `error`,\n        --  submitting the form will succeed with an `Ok`\n        |> Yafl.submit form\n\n    --> Ok 0\n\n","type":"(output -> Maybe.Maybe String.String) -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input output"},{"name":"warningAt","comment":" Validate a `Field` and specify a warning to display on a _different_ `Field`.\nThis is useful when you are doing validation that involves multiple fields, but\nyou only want to display a warning on one field.\n\n    import Examples exposing (fields)\n    import Yafl\n\n    passwordField =\n        fields.string\n            |> Yafl.identifier \"password\"\n\n    confirmField =\n        fields.string\n            |> Yafl.identifier \"confirm\"\n\n    form =\n        Yafl.succeed\n            (\\password confirm -> { password = password, confirm = confirm })\n            |> Yafl.andMap .passwordField passwordField\n            |> Yafl.andMap .confirmField confirmField\n            |> Yafl.warningAt confirmField\n                (\\{ password, confirm } ->\n                    if password == confirm then\n                        Nothing\n\n                    else\n                        Just \"Passwords do not match\"\n                )\n\n    form\n        |> Yafl.init\n        |> Tuple.first\n        |> Yafl.load form\n            { passwordField = Just \"password123\"\n            , confirmField = Just \"password124\"\n            }\n        |> Tuple.first\n        --  since we used `warningAt` instead of `errorAt`,\n        --  submitting the form will succeed with an `Ok`\n        |> Yafl.submit form\n\n    --> Ok { password = \"password123\", confirm = \"password124\" }\n\n","type":"Yafl.Field formModel formMsg Yafl.HasId widgetMsg2 input2 output2 -> (output -> Maybe.Maybe String.String) -> Yafl.Field formModel formMsg id widgetMsg input output -> Yafl.Field formModel formMsg id widgetMsg input output"}],"binops":[]}]