[{"name":"Effect.Browser","comment":" This module helps you set up an Elm `Program` with functions like\n[`sandbox`](#sandbox) and [`document`](#document).\n\n\n# Sandboxes\n\n@docs sandbox\n\n\n# Elements\n\n@docs element\n\n\n# Documents\n\n@docs document, Document\n\n\n# Applications\n\n@docs application, UrlRequest\n\n","unions":[],"aliases":[{"name":"Document","comment":" This data specifies the `<title>` and all of the nodes that should go in\nthe `<body>`. This means you can update the title as your application changes.\nMaybe your \"single-page app\" navigates to a \"different page\", maybe a calendar\napp shows an accurate date in the title, etc.\n\n> **Note about CSS:** This looks similar to an `<html>` document, but this is\n> not the place to manage CSS assets. If you want to work with CSS, there are\n> a couple ways:\n>\n> 1.  Packages like [`rtfeldman/elm-css`][elm-css] give all of the features\n>     of CSS without any CSS files. You can add all the styles you need in your\n>     `view` function, and there is no need to worry about class names matching.\n>\n> 2.  Compile your Elm code to JavaScript with `elm make --output=elm.js` and\n>     then make your own HTML file that loads `elm.js` and the CSS file you want.\n>     With this approach, it does not matter where the CSS comes from. Write it\n>     by hand. Generate it. Whatever you want to do.\n>\n> 3.  If you need to change `<link>` tags dynamically, you can send messages\n>     out a port to do it in JavaScript.\n>\n> The bigger point here is that loading assets involves touching the `<head>`\n> as an implementation detail of browsers, but that does not mean it should be\n> the responsibility of the `view` function in Elm. So we do it differently!\n\n[elm-css]: /packages/rtfeldman/elm-css/latest/\n\n","args":["msg"],"type":"Browser.Document msg"},{"name":"UrlRequest","comment":" All links in an [`application`](#application) create a `UrlRequest`. So\nwhen you click `<a href=\"/home\">Home</a>`, it does not just navigate! It\nnotifies `onUrlRequest` that the user wants to change the `Url`.\n\n\n### `Internal` vs `External`\n\nImagine we are browsing `https://example.com`. An `Internal` link would be\nlike:\n\n  - `settings#privacy`\n  - `/home`\n  - `https://example.com/home`\n  - `//example.com/home`\n\nAll of these links exist under the `https://example.com` domain. An `External`\nlink would be like:\n\n  - `https://elm-lang.org/examples`\n  - `https://other.example.com/home`\n  - `http://example.com/home`\n\nAnything that changes the domain. Notice that changing the protocol from\n`https` to `http` is considered a different domain! (And vice versa!)\n\n\n### Purpose\n\nHaving a `UrlRequest` requires a case in your `update` like this:\n\n    import Browser exposing (..)\n    import Browser.Navigation as Nav\n    import Url\n\n    type Msg\n        = ClickedLink UrlRequest\n\n    update : Msg -> Model -> ( Model, Cmd msg )\n    update msg model =\n        case msg of\n            ClickedLink urlRequest ->\n                case urlRequest of\n                    Internal url ->\n                        ( model\n                        , Nav.pushUrl model.key (Url.toString url)\n                        )\n\n                    External url ->\n                        ( model\n                        , Nav.load url\n                        )\n\nThis is useful because it gives you a chance to customize the behavior in each\ncase. Maybe on some `Internal` links you save the scroll position with\n[`Browser.Dom.getViewport`](Browser-Dom#getViewport) so you can restore it\nlater. Maybe on `External` links you persist parts of the `Model` on your\nservers before leaving. Whatever you need to do!\n\n**Note:** Knowing the scroll position is not enough to restore it! What if the\nbrowser dimensions change? The scroll position will not correlate with\n&ldquo;what was on screen&rdquo; anymore. So it may be better to remember\n&ldquo;what was on screen&rdquo; and recreate the position based on that. For\nexample, in a Wikipedia article, remember the header that they were looking at\nmost recently. [`Browser.Dom.getElement`](Browser-Dom#getElement) is designed\nfor figuring that out!\n\n","args":[],"type":"Browser.UrlRequest"}],"values":[{"name":"application","comment":" Create an application that manages [`Url`][url] changes.\n\n**When the application starts**, `init` gets the initial `Url`. You can show\ndifferent things depending on the `Url`!\n\n**When someone clicks a link**, like `<a href=\"/home\">Home</a>`, it always goes\nthrough `onUrlRequest`. The resulting message goes to your `update` function,\ngiving you a chance to save scroll position or persist data before changing\nthe URL yourself with [`pushUrl`][bnp] or [`load`][bnl]. More info on this in\nthe [`UrlRequest`](#UrlRequest) docs!\n\n**When the URL changes**, the new `Url` goes through `onUrlChange`. The\nresulting message goes to `update` where you can decide what to show next.\n\nApplications always use the [`Browser.Navigation`][bn] module for precise\ncontrol over `Url` changes.\n\n**More Info:** Here are some example usages of `application` programs:\n\n  - [RealWorld example app](https://github.com/rtfeldman/elm-spa-example)\n  - [Elm’s package website](https://github.com/elm/package.elm-lang.org)\n\nThese are quite advanced Elm programs, so be sure to go through [the guide][g]\nfirst to get a solid conceptual foundation before diving in! If you start\nreading a calculus book from page 314, it might seem confusing. Same here!\n\n**Note:** Can an [`element`](#element) manage the URL too? Read [this]!\n\n[g]: https://guide.elm-lang.org/\n[bn]: Browser-Navigation\n[bnp]: Browser-Navigation#pushUrl\n[bnl]: Browser-Navigation#load\n[url]: /packages/elm/url/latest/Url#Url\n[this]: https://github.com/elm/browser/blob/1.0.2/notes/navigation-in-elements.md\n\n","type":"{ init : flags -> Url.Url -> Effect.Browser.Navigation.Key -> ( model, Effect.Command.Command Effect.Command.FrontendOnly Basics.Never msg ), view : model -> Effect.Browser.Document msg, update : msg -> model -> ( model, Effect.Command.Command Effect.Command.FrontendOnly Basics.Never msg ), subscriptions : model -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg, onUrlRequest : Effect.Browser.UrlRequest -> msg, onUrlChange : Url.Url -> msg } -> Platform.Program flags model msg"},{"name":"document","comment":" Create an HTML document managed by Elm. This expands upon what `element`\ncan do in that `view` now gives you control over the `<title>` and `<body>`.\n","type":"{ init : flags -> ( model, Effect.Command.Command Effect.Command.FrontendOnly Basics.Never msg ), view : model -> Effect.Browser.Document msg, update : msg -> model -> ( model, Effect.Command.Command Effect.Command.FrontendOnly Basics.Never msg ), subscriptions : model -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg } -> Platform.Program flags model msg"},{"name":"element","comment":" Create an HTML element managed by Elm. The resulting elements are easy to\nembed in larger JavaScript projects, and lots of companies that use Elm\nstarted with this approach! Try it out on something small. If it works, great,\ndo more! If not, revert, no big deal.\n\nUnlike a [`sandbox`](#sandbox), an `element` can talk to the outside world in\na couple ways:\n\n  - `Cmd` &mdash; you can “command” the Elm runtime to do stuff, like HTTP.\n  - `Sub` &mdash; you can “subscribe” to event sources, like clock ticks.\n  - `flags` &mdash; JavaScript can pass in data when starting the Elm program\n  - `ports` &mdash; set up a client-server relationship with JavaScript\n\nAs you read [the guide][guide] you will run into a bunch of examples of `element`\nin [this section][fx]. You can learn more about flags and ports in [the interop\nsection][interop].\n\n[guide]: https://guide.elm-lang.org/\n[fx]: https://guide.elm-lang.org/effects/\n[interop]: https://guide.elm-lang.org/interop/\n\n","type":"{ init : flags -> ( model, Effect.Command.Command Effect.Command.FrontendOnly Basics.Never msg ), view : model -> Html.Html msg, update : msg -> model -> ( model, Effect.Command.Command Effect.Command.FrontendOnly Basics.Never msg ), subscriptions : model -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg } -> Platform.Program flags model msg"},{"name":"sandbox","comment":" Create a “sandboxed” program that cannot communicate with the outside\nworld.\n\nThis is great for learning the basics of [The Elm Architecture][tea]. You can\nsee sandboxes in action in the following examples:\n\n  - [Buttons](https://guide.elm-lang.org/architecture/buttons.html)\n  - [Text Fields](https://guide.elm-lang.org/architecture/text_fields.html)\n  - [Forms](https://guide.elm-lang.org/architecture/forms.html)\n\nThose are nice, but **I very highly recommend reading [this guide][guide]\nstraight through** to really learn how Elm works. Understanding the\nfundamentals actually pays off in this language!\n\n[tea]: https://guide.elm-lang.org/architecture/\n[guide]: https://guide.elm-lang.org/\n\n","type":"{ init : model, view : model -> Html.Html msg, update : msg -> model -> model } -> Platform.Program () model msg"}],"binops":[]},{"name":"Effect.Browser.Dom","comment":" This module allows you to manipulate the DOM in various ways. It covers:\n\n  - Focus and blur input elements.\n  - Get the `width` and `height` of elements.\n  - Get the `x` and `y` coordinates of elements.\n  - Figure out the scroll position.\n  - Change the scroll position!\n\nWe use different terminology than JavaScript though...\n\n\n# Terminology\n\nHave you ever thought about how &ldquo;scrolling&rdquo; is a metaphor about\nscrolls? Like hanging scrolls of caligraphy made during the Han Dynasty\nin China?\n\nThis metaphor falls apart almost immediately though. For example, many scrolls\nread horizontally! Like a [Sefer Torah][torah] or [Chinese Handscrolls][hand].\nThe two sides move independently, sometimes kept in place with stones. What is\na scroll bar in this world? And [hanging scrolls][hang] (which _are_ displayed\nvertically) do not &ldquo;scroll&rdquo; at all! They hang!\n\nSo in JavaScript, we start with a badly stretched metaphor and add a bunch of\nDOM details like padding, borders, and margins. How do those relate to scrolls?\nFor example, JavaScript has `clientWidth`. Client like a feudal state that pays\ntribute to the emperor? And `offsetHeight`. Can an offset even have height? And\nwhat has that got to do with scrolls?\n\nSo instead of inheriting this metaphorical hodge-podge, we use terminology from\n3D graphics. You have a **scene** containing all your elements and a **viewport**\ninto the scene. I think it ends up being a lot clearer, but you can evaluate\nfor yourself when you see the diagrams later!\n\n**Note:** For more scroll facts, I recommend [A Day on the Grand Canal with\nthe Emperor of China or: Surface Is Illusion But So Is Depth][doc] where David\nHockney explores the history of _perspective_ in art. Really interesting!\n\n[torah]: https://en.wikipedia.org/wiki/Sefer_Torah\n[hand]: https://www.metmuseum.org/toah/hd/chhs/hd_chhs.htm\n[hang]: https://en.wikipedia.org/wiki/Hanging_scroll\n[doc]: https://www.imdb.com/title/tt0164525/\n\n\n# DOM node ids\n\n@docs HtmlId, id, idToAttribute, idToString\n\n\n# Focus\n\n@docs focus, blur, Error\n\n\n# Get Viewport\n\n@docs getViewport, Viewport, getViewportOf\n\n\n# Set Viewport\n\n@docs setViewport, setViewportOf\n\n\n# Position\n\n@docs getElement, Element\n\n","unions":[{"name":"Error","comment":" Many functions in this module look up DOM nodes up by their `id`. If you\nask for an `id` that is not in the DOM, you will get this error.\n","args":[],"cases":[["NotFound",["Effect.Browser.Dom.HtmlId"]]]},{"name":"HtmlId","comment":" The id of a DOM node.\n","args":[],"cases":[]}],"aliases":[{"name":"Element","comment":" A bunch of information about the position and size of an element relative\nto the overall scene.\n\n![getElement](https://elm.github.io/browser/v1/getElement.svg)\n\n","args":[],"type":"{ scene : { width : Basics.Float, height : Basics.Float }, viewport : { x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float }, element : { x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float } }"},{"name":"Viewport","comment":" All the information about the current viewport.\n\n![getViewport](https://elm.github.io/browser/v1/getViewport.svg)\n\n","args":[],"type":"{ scene : { width : Basics.Float, height : Basics.Float }, viewport : { x : Basics.Float, y : Basics.Float, width : Basics.Float, height : Basics.Float } }"}],"values":[{"name":"blur","comment":" Find a DOM node by `id` and make it lose focus. So if you wanted a node\nlike `<input type=\"text\" id=\"search-box\">` to lose focus you could say:\n\n    import Browser.Dom as Dom\n    import Task\n\n    type Msg\n        = NoOp\n\n    unfocusSearchBox : Cmd Msg\n    unfocusSearchBox =\n        Task.attempt (\\_ -> NoOp) (Dom.blur \"search-box\")\n\nNotice that this code ignores the possibility that `search-box` is not used\nas an `id` by any node, failing silently in that case. It would be better to\nlog the failure with whatever error reporting system you use.\n\n","type":"Effect.Browser.Dom.HtmlId -> Effect.Task.Task Effect.Command.FrontendOnly Effect.Browser.Dom.Error ()"},{"name":"focus","comment":" Find a DOM node by `id` and focus on it. So if you wanted to focus a node\nlike `<input type=\"text\" id=\"search-box\">` you could say:\n\n    import Browser.Dom as Dom\n    import Task\n\n    type Msg\n        = NoOp\n\n    focusSearchBox : Cmd Msg\n    focusSearchBox =\n        Task.attempt (\\_ -> NoOp) (Dom.focus \"search-box\")\n\nNotice that this code ignores the possibility that `search-box` is not used\nas an `id` by any node, failing silently in that case. It would be better to\nlog the failure with whatever error reporting system you use.\n\n","type":"Effect.Browser.Dom.HtmlId -> Effect.Task.Task Effect.Command.FrontendOnly Effect.Browser.Dom.Error ()"},{"name":"getElement","comment":" Get position information about specific elements. Say we put\n`id \"jesting-aside\"` on the seventh paragraph of the text. When we call\n`getElement \"jesting-aside\"` we would get the following information:\n\n![getElement](https://elm.github.io/browser/v1/getElement.svg)\n\nThis can be useful for:\n\n  - **Scrolling** &mdash; Pair this information with `setViewport` to scroll\n    specific elements into view. This gives you a lot of control over where exactly\n    the element would be after the viewport moved.\n\n  - **Drag and Drop** &mdash; As of this writing, `touchmove` events do not tell\n    you which element you are currently above. To figure out if you have dragged\n    something over the target, you could see if the `pageX` and `pageY` of the\n    touch are inside the `x`, `y`, `width`, and `height` of the target element.\n\n**Note:** This corresponds to JavaScript&rsquo;s [`getBoundingClientRect`][gbcr],\nso **the element&rsquo;s margins are included in its `width` and `height`**.\nWith scrolling, maybe you want to include the margins. With drag-and-drop, you\nprobably do not, so some folks set the margins to zero and put the target\nelement in a `<div>` that adds the spacing. Just something to be aware of!\n\n[gbcr]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect\n\n","type":"Effect.Browser.Dom.HtmlId -> Effect.Task.Task Effect.Command.FrontendOnly Effect.Browser.Dom.Error Effect.Browser.Dom.Element"},{"name":"getViewport","comment":" Get information on the current viewport of the browser.\n\n![getViewport](https://elm.github.io/browser/v1/getViewport.svg)\n\nIf you want to move the viewport around (i.e. change the scroll position) you\ncan use [`setViewport`](#setViewport) which change the `x` and `y` of the\nviewport.\n\n","type":"Effect.Task.Task Effect.Command.FrontendOnly x Effect.Browser.Dom.Viewport"},{"name":"getViewportOf","comment":" Just like `getViewport`, but for any scrollable DOM node. Say we have an\napplication with a chat box in the bottow right corner like this:\n\n![chat](https://elm.github.io/browser/v1/chat.svg)\n\nThere are probably a whole bunch of messages that are not being shown. You\ncould scroll up to see them all. Well, we can think of that chat box is a\nviewport into a scene!\n\n![getViewportOf](https://elm.github.io/browser/v1/getViewportOf.svg)\n\nThis can be useful with [`setViewportOf`](#setViewportOf) to make sure new\nmessages always appear on the bottom.\n\nThe viewport size _does not_ include the border or margins.\n\n**Note:** This data is collected from specific fields in JavaScript, so it\nmay be helpful to know that:\n\n  - `scene.width` = [`scrollWidth`][sw]\n  - `scene.height` = [`scrollHeight`][sh]\n  - `viewport.x` = [`scrollLeft`][sl]\n  - `viewport.y` = [`scrollTop`][st]\n  - `viewport.width` = [`clientWidth`][cw]\n  - `viewport.height` = [`clientHeight`][ch]\n\nNeither [`offsetWidth`][ow] nor [`offsetHeight`][oh] are available. The theory\nis that (1) the information can always be obtained by using `getElement` on a\nnode without margins, (2) no cases came to mind where you actually care in the\nfirst place, and (3) it is available through ports if it is really needed.\nIf you have a case that really needs it though, please share your specific\nscenario in an issue! Nicely presented case studies are the raw ingredients for\nAPI improvements!\n\n[sw]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidth\n[sh]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight\n[st]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop\n[sl]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft\n[cw]: https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth\n[ch]: https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight\n[ow]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth\n[oh]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight\n\n","type":"Effect.Browser.Dom.HtmlId -> Effect.Task.Task Effect.Command.FrontendOnly Effect.Browser.Dom.Error Effect.Browser.Dom.Viewport"},{"name":"id","comment":" Create an HtmlId from a String.\n","type":"String.String -> Effect.Browser.Dom.HtmlId"},{"name":"idToAttribute","comment":" Convert a HtmlId to an Html.Attribute that you can assign to a DOM node.\n\n    import Effect.Browser.Dom as Dom\n    import Html\n\n    buttonId =\n        Dom.id \"my-button\"\n\n    button =\n        Html.button [ Dom.idToAttribute buttonId ] []\n\n","type":"Effect.Browser.Dom.HtmlId -> Html.Attribute msg"},{"name":"idToString","comment":" Convert an HtmlId to a String.\n","type":"Effect.Browser.Dom.HtmlId -> String.String"},{"name":"setViewport","comment":" Change the `x` and `y` offset of the browser viewport immediately. For\nexample, you could make a command to jump to the top of the page:\n\n    import Browser.Dom as Dom\n    import Task\n\n    type Msg\n        = NoOp\n\n    resetViewport : Cmd Msg\n    resetViewport =\n        Task.perform (\\_ -> NoOp) (Dom.setViewport 0 0)\n\nThis sets the viewport offset to zero.\n\nThis could be useful with `Browser.application` where you may want to reset\nthe viewport when the URL changes. Maybe you go to a &ldquo;new page&rdquo;\nand want people to start at the top!\n\n","type":"Basics.Float -> Basics.Float -> Effect.Task.Task Effect.Command.FrontendOnly x ()"},{"name":"setViewportOf","comment":" Change the `x` and `y` offset of a DOM node&rsquo;s viewport by ID. This\nis common in text messaging and chat rooms, where once the messages fill the\nscreen, you want to always be at the very bottom of the message chain. This\nway the latest message is always on screen! You could do this:\n\n    import Browser.Dom as Dom\n    import Task\n\n    type Msg\n        = NoOp\n\n    jumpToBottom : String -> Cmd Msg\n    jumpToBottom id =\n        Dom.getViewportOf id\n            |> Task.andThen (\\info -> Dom.setViewportOf id 0 info.scene.height)\n            |> Task.attempt (\\_ -> NoOp)\n\nSo you could call `jumpToBottom \"chat-box\"` whenever you add a new message.\n\n**Note 1:** What happens if the viewport is placed out of bounds? Where there\nis no `scene` to show? To avoid this question, the `x` and `y` offsets are\nclamped such that the viewport is always fully within the `scene`. So when\n`jumpToBottom` sets the `y` offset of the viewport to the `height` of the\n`scene` (i.e. too far!) it relies on this clamping behavior to put the viewport\nback in bounds.\n\n**Note 2:** The example ignores when the element ID is not found, but it would\nbe great to log that information. It means there may be a bug or a dead link\nsomewhere!\n\n","type":"Effect.Browser.Dom.HtmlId -> Basics.Float -> Basics.Float -> Effect.Task.Task Effect.Command.FrontendOnly Effect.Browser.Dom.Error ()"}],"binops":[]},{"name":"Effect.Browser.Events","comment":" In JavaScript, information about the root of an HTML document is held in\nthe `document` and `window` objects. This module lets you create event\nlisteners on those objects for the following topics: [animation](#animation),\n[keyboard](#keyboard), [mouse](#mouse), and [window](#window).\n\nIf there is something else you need, use [ports] to do it in JavaScript!\n\n[ports]: https://guide.elm-lang.org/interop/ports.html\n\n\n# Animation\n\n@docs onAnimationFrame, onAnimationFrameDelta\n\n\n# Keyboard\n\n@docs onKeyPress, onKeyDown, onKeyUp\n\n\n# Mouse\n\n@docs onClick, onMouseMove, onMouseDown, onMouseUp\n\n\n# Window\n\n@docs onResize, onVisibilityChange, Visibility\n\n","unions":[{"name":"Visibility","comment":" Value describing whether the page is hidden or visible.\n","args":[],"cases":[["Visible",[]],["Hidden",[]]]}],"aliases":[],"values":[{"name":"onAnimationFrame","comment":" An animation frame triggers about 60 times per second. Get the POSIX time\non each frame. (See [`elm/time`](/packages/elm/time/latest) for more info on\nPOSIX times.)\n\n**Note:** Browsers have their own render loop, repainting things as fast as\npossible. If you want smooth animations in your application, it is helpful to\nsync up with the browsers natural refresh rate. This hooks into JavaScript's\n`requestAnimationFrame` function.\n\n","type":"(Time.Posix -> msg) -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onAnimationFrameDelta","comment":" Just like `onAnimationFrame`, except message is the time in milliseconds\nsince the previous frame. So you should get a sequence of values all around\n`1000 / 60` which is nice for stepping animations by a time delta.\n","type":"(Duration.Duration -> msg) -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onClick","comment":" Subscribe to mouse clicks anywhere on screen. Maybe you need to create a\ncustom drop down. You could listen for clicks when it is open, letting you know\nif someone clicked out of it:\n\n    import Browser.Events as Events\n    import Json.Decode as D\n\n    type Msg\n        = ClickOut\n\n    subscriptions : Model -> Sub Msg\n    subscriptions model =\n        case model.dropDown of\n            Closed _ ->\n                Sub.none\n\n            Open _ ->\n                Events.onClick (D.succeed ClickOut)\n\n","type":"Json.Decode.Decoder msg -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onKeyDown","comment":" Subscribe to get codes whenever a key goes down. This can be useful for\ncreating games. Maybe you want to know if people are pressing `w`, `a`, `s`,\nor `d` at any given time.\n\n**Note:** Check out [this advice][note] to learn more about decoding key codes.\nIt is more complicated than it should be.\n\n[note]: https://github.com/elm/browser/blob/1.0.2/notes/keyboard.md\n\n","type":"Json.Decode.Decoder msg -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onKeyPress","comment":" Subscribe to key presses that normally produce characters. So you should\nnot rely on this for arrow keys.\n\n**Note:** Check out [this advice][note] to learn more about decoding key codes.\nIt is more complicated than it should be.\n\n[note]: https://github.com/elm/browser/blob/1.0.2/notes/keyboard.md\n\n","type":"Json.Decode.Decoder msg -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onKeyUp","comment":" Subscribe to get codes whenever a key goes up. Often used in combination\nwith [`onVisibilityChange`](#onVisibilityChange) to be sure keys do not appear\nto down and never come back up.\n","type":"Json.Decode.Decoder msg -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onMouseDown","comment":" Subscribe to get mouse information whenever the mouse button goes down.\n","type":"Json.Decode.Decoder msg -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onMouseMove","comment":" Subscribe to mouse moves anywhere on screen.\n\nYou could use this to implement resizable panels like in Elm's online code\neditor. Check out the example imprementation [here][drag].\n\n[drag]: https://github.com/elm/browser/blob/1.0.2/examples/src/Drag.elm\n\n**Note:** Unsubscribe if you do not need these events! Running code on every\nsingle mouse movement can be very costly, and it is recommended to only\nsubscribe when absolutely necessary.\n\n","type":"Json.Decode.Decoder msg -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onMouseUp","comment":" Subscribe to get mouse information whenever the mouse button goes up.\nOften used in combination with [`onVisibilityChange`](#onVisibilityChange)\nto be sure keys do not appear to down and never come back up.\n","type":"Json.Decode.Decoder msg -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onResize","comment":" Subscribe to any changes in window size.\n\nFor example, you could track the current width by saying:\n\n    import Browser.Events as E\n\n    type Msg\n        = GotNewWidth Int\n\n    subscriptions : model -> Cmd Msg\n    subscriptions _ =\n        E.onResize (\\w h -> GotNewWidth w)\n\n**Note:** This is equivalent to getting events from [`window.onresize`][resize].\n\n[resize]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onresize\n\n","type":"(Basics.Int -> Basics.Int -> msg) -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"onVisibilityChange","comment":" Subscribe to any visibility changes, like if the user switches to a\ndifferent tab or window. When the user looks away, you may want to:\n\n  - Pause a timer.\n  - Pause an animation.\n  - Pause video or audio.\n  - Pause an image carousel.\n  - Stop polling a server for new information.\n  - Stop waiting for an [`onKeyUp`](#onKeyUp) event.\n\n","type":"(Effect.Browser.Events.Visibility -> msg) -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"}],"binops":[]},{"name":"Effect.Browser.Navigation","comment":" This module helps you manage the browser’s URL yourself. This is the\ncrucial trick when using [`Browser.application`](Browser#application).\n\nThe most important function is [`pushUrl`](#pushUrl) which changes the\naddress bar _without_ starting a page load.\n\n\n## What is a page load?\n\n1.  Request a new HTML document. The page goes blank.\n2.  As the HTML loads, request any `<script>` or `<link>` resources.\n3.  A `<script>` may mutate the document, so these tags block rendering.\n4.  When _all_ of the assets are loaded, actually render the page.\n\nThat means the page will go blank for at least two round-trips to the servers!\nYou may have 90% of the data you need and be blocked on a font that is taking\na long time. Still blank!\n\n\n## How does `pushUrl` help?\n\nThe `pushUrl` function changes the URL, but lets you keep the current HTML.\nThis means the page _never_ goes blank. Instead of making two round-trips to\nthe server, you load whatever assets you want from within Elm. Maybe you do\nnot need any round-trips! Meanwhile, you retain full control over the UI, so\nyou can show a loading bar, show information as it loads, etc. Whatever you\nwant!\n\n\n# Navigate within Page\n\n@docs Key, pushUrl, replaceUrl, back, forward\n\n\n# Navigate to other Pages\n\n@docs load, reload, reloadAndSkipCache, fromInternalKey\n\n\n# Temporary integration\n\n@docs withRealKey\n\n","unions":[{"name":"Key","comment":" A navigation `Key` is needed to create navigation commands that change the\nURL. That includes [`pushUrl`](#pushUrl), [`replaceUrl`](#replaceUrl),\n[`back`](#back), and [`forward`](#forward).\n\nYou only get access to a `Key` when you create your program with\n[`Browser.application`](Browser#application), guaranteeing that your program is\nequipped to detect these URL changes. If `Key` values were available in other\nkinds of programs, unsuspecting programmers would be sure to run into some\n[annoying bugs][bugs] and learn a bunch of techniques the hard way!\n\n[bugs]: https://github.com/elm/browser/blob/1.0.2/notes/navigation-in-elements.md\n\n","args":[],"cases":[]}],"aliases":[],"values":[{"name":"back","comment":" Go back some number of pages. So `back 1` goes back one page, and `back 2`\ngoes back two pages.\n\n**Note:** You only manage the browser history that _you_ created. Think of this\nlibrary as letting you have access to a small part of the overall history. So\nif you go back farther than the history you own, you will just go back to some\nother website!\n\n","type":"Effect.Browser.Navigation.Key -> Basics.Int -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"forward","comment":" Go forward some number of pages. So `forward 1` goes forward one page, and\n`forward 2` goes forward two pages. If there are no more pages in the future,\nthis will do nothing.\n\n**Note:** You only manage the browser history that _you_ created. Think of this\nlibrary as letting you have access to a small part of the overall history. So\nif you go forward farther than the history you own, the user will end up on\nwhatever website they visited next!\n\n","type":"Effect.Browser.Navigation.Key -> Basics.Int -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"fromInternalKey","comment":" Please ignore\n","type":"Effect.Internal.NavigationKey -> Effect.Browser.Navigation.Key"},{"name":"load","comment":" Leave the current page and load the given URL. **This always results in a\npage load**, even if the provided URL is the same as the current one.\n\n    gotoElmWebsite : Cmd msg\n    gotoElmWebsite =\n        load \"https://elm-lang.org\"\n\nCheck out the [`elm/url`][url] package for help building URLs. The\n[`Url.absolute`][abs] and [`Url.relative`][rel] functions can be particularly\nhandy!\n\n[url]: /packages/elm/url/latest\n[abs]: /packages/elm/url/latest/Url#absolute\n[rel]: /packages/elm/url/latest/Url#relative\n\n","type":"String.String -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"pushUrl","comment":" Change the URL, but do not trigger a page load.\n\nThis will add a new entry to the browser history.\n\nCheck out the [`elm/url`][url] package for help building URLs. The\n[`Url.Builder.absolute`][abs] and [`Url.Builder.relative`][rel] functions can\nbe particularly handy!\n\n[url]: /packages/elm/url/latest\n[abs]: /packages/elm/url/latest/Url-Builder#absolute\n[rel]: /packages/elm/url/latest/Url-Builder#relative\n\n**Note:** If the user has gone `back` a few pages, there will be &ldquo;future\npages&rdquo; that the user can go `forward` to. Adding a new URL in that\nscenario will clear out any future pages. It is like going back in time and\nmaking a different choice.\n\n","type":"Effect.Browser.Navigation.Key -> String.String -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"reload","comment":" Reload the current page. **This always results in a page load!**\nThis may grab resources from the browser cache, so use\n[`reloadAndSkipCache`](#reloadAndSkipCache)\nif you want to be sure that you are not loading any cached resources.\n","type":"Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"reloadAndSkipCache","comment":" Reload the current page without using the browser cache. **This always\nresults in a page load!** It is more common to want [`reload`](#reload).\n","type":"Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"replaceUrl","comment":" Change the URL, but do not trigger a page load.\n\nThis _will not_ add a new entry to the browser history.\n\nThis can be useful if you have search box and you want the `?search=hats` in\nthe URL to match without adding a history entry for every single key stroke.\nImagine how annoying it would be to click `back` thirty times and still be on\nthe same page!\n\n**Note:** Browsers may rate-limit this function by throwing an exception. The\ndiscussion [here](https://bugs.webkit.org/show_bug.cgi?id=156115) suggests\nthat the limit is 100 calls per 30 second interval in Safari in 2016. It also\nsuggests techniques for people changing the URL based on scroll position.\n\n","type":"Effect.Browser.Navigation.Key -> String.String -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"withRealKey","comment":" Escape hatch for extracting a Browser.Navigation.Key in non-test code. **This will\ncause a stack overflow if used in tests!**.\n","type":"Effect.Browser.Navigation.Key -> Browser.Navigation.Key"}],"binops":[]},{"name":"Effect.Command","comment":"\n\n> **Note:** Elm has **managed effects**, meaning that things like HTTP\n> requests or writing to disk are all treated as _data_ in Elm. When this\n> data is given to the Elm runtime system, it can do some “query optimization”\n> before actually performing the effect. Perhaps unexpectedly, this managed\n> effects idea is the heart of why Elm is so nice for testing, reuse,\n> reproducibility, etc.\n>\n> Elm has two kinds of managed effects: commands and subscriptions.\n\n\n# Commands\n\n@docs Command, none, batch, sendToJs, FrontendOnly, BackendOnly\n\n\n# Fancy Stuff\n\n@docs map\n\n\n# Temporary integration\n\n@docs fromCmd\n\n","unions":[],"aliases":[{"name":"BackendOnly","comment":" `Command`s and `Subscription`s with this type variable indicate that they can only be used on the backend.\n\n    import Command exposing (BackendOnly, Command)\n    import Effect.Lamdera exposing (ClientId)\n\n    sendData : ClientId -> Command BackendOnly toMsg msg\n    sendData clientId =\n        Effect.Lamdera.sendToFrontend clientId data\n\n","args":[],"type":"Effect.Internal.BackendOnly"},{"name":"Command","comment":" A command is a way of telling Elm, “Hey, I want you to do this thing!”\nSo if you want to send an HTTP request, you would need to command Elm to do it.\nOr if you wanted to ask for geolocation, you would need to command Elm to go\nget it.\n\nEvery `Cmd` specifies (1) which effects you need access to and (2) the type of\nmessages that will come back into your application.\n\n**Note:** Do not worry if this seems confusing at first! As with every Elm user\never, commands will make more sense as you work through [the Elm Architecture\nTutorial](https://guide.elm-lang.org/architecture/) and see how they\nfit into a real application!\n\n","args":["restriction","toMsg","msg"],"type":"Effect.Internal.Command restriction toMsg msg"},{"name":"FrontendOnly","comment":" `Command`s and `Subscription`s with this type variable indicate that they can only be used on the frontend.\n\n    import Command exposing (Command, FrontendOnly)\n    import Effect.File.Select\n\n    download : Command FrontendOnly toMsg msg\n    download =\n        Effect.File.Select \"/my-file.txt\"\n\n","args":[],"type":"Effect.Internal.FrontendOnly"}],"values":[{"name":"batch","comment":" When you need the runtime system to perform a couple commands, you\ncan batch them together. Each is handed to the runtime at the same time,\nand since each can perform arbitrary operations in the world, there are\nno ordering guarantees about the results.\n\n**Note:** `Cmd.none` and `Cmd.batch [ Cmd.none, Cmd.none ]` and `Cmd.batch []`\nall do the same thing.\n\n","type":"List.List (Effect.Command.Command restriction toMsg msg) -> Effect.Command.Command restriction toMsg msg"},{"name":"fromCmd","comment":" Escape hatch for `Cmd msg` values.\n\nNo tests can be applied to this value, it will be completely ignored by program-test.\n\nYou should not be using this function except temporarily in a progressive implementation of program-test.\n\n","type":"String.String -> Platform.Cmd.Cmd msg -> Effect.Command.Command restriction toMsg msg"},{"name":"map","comment":" Transform the messages produced by a command.\nVery similar to [`Html.map`](/packages/elm/html/latest/Html#map).\n\nThis is very rarely useful in well-structured Elm code, so definitely read the\nsection on [structure] in the guide before reaching for this!\n\n[structure]: https://guide.elm-lang.org/webapps/structure.html\n\n","type":"(toBackendA -> toBackendB) -> (frontendMsgA -> frontendMsgB) -> Effect.Command.Command restriction toBackendA frontendMsgA -> Effect.Command.Command restriction toBackendB frontendMsgB"},{"name":"none","comment":" Tell the runtime that there are no commands.\n","type":"Effect.Command.Command restriction toMsg msg"},{"name":"sendToJs","comment":" This function sends data to JS land. Below is an example of how to use it.\n\n    import Command\n    import Json.Encode\n\n    port copyToClipboardPort : Cmd Json.Encode.Value -> msg\n\n    copyToClipboard value =\n        Command.sendToJs \"copyToClipboardPort\" copyToClipboardPort value\n\n","type":"String.String -> (Json.Encode.Value -> Platform.Cmd.Cmd msg) -> Json.Encode.Value -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"}],"binops":[]},{"name":"Effect.File","comment":"\n\n\n# Files\n\n@docs File, decoder\n\n\n# Extract Content\n\n@docs toString, toBytes, toUrl\n\n\n# Read Metadata\n\n@docs name, mime, size, lastModified, toInternalFile, fromInternalFile\n\n","unions":[{"name":"File","comment":" Represents an uploaded file. From there you can read the content, check\nthe metadata, send it over [`elm/http`](/packages/elm/http/latest), etc.\n","args":[],"cases":[]}],"aliases":[],"values":[{"name":"decoder","comment":" Decode `File` values. For example, if you want to create a drag-and-drop\nfile uploader, you can listen for `drop` events with a decoder like this:\n\n    import File\n    import Json.Decode exposing (Decoder, field, list)\n\n    files : Decode.Decoder (List File)\n    files =\n        field \"dataTransfer\" (field \"files\" (list File.decoder))\n\nOnce you have the files, you can use functions like [`File.toString`](#toString)\nto process the content. Or you can send the file along to someone else with the\n[`elm/http`](/packages/elm/http/latest) package.\n\n","type":"Json.Decode.Decoder Effect.File.File"},{"name":"fromInternalFile","comment":" Please ignore\n","type":"Effect.Internal.File -> Effect.File.File"},{"name":"lastModified","comment":" Get the time the file was last modified.\n\n    lastModified file1 -- 1536872423\n\n    lastModified file2 -- 860581394\n\n    lastModified file3 -- 1340375405\n\nLearn more about how time is represented by reading through the\n[`elm/time`](/packages/elm/time/latest) package!\n\n","type":"Effect.File.File -> Time.Posix"},{"name":"mime","comment":" Get the MIME type of a file.\n\n    mime file1 == \"text/markdown\"\n\n    mime file2 == \"image/gif\"\n\n    mime file3 == \"application/zip\"\n\n","type":"Effect.File.File -> String.String"},{"name":"name","comment":" Get the name of a file.\n\n    name file1 == \"README.md\"\n\n    name file2 == \"math.gif\"\n\n    name file3 == \"archive.zip\"\n\n","type":"Effect.File.File -> String.String"},{"name":"size","comment":" Get the size of the file in bytes.\n\n    size file1 == 395\n\n    size file2 == 65813\n\n    size file3 == 81481\n\n","type":"Effect.File.File -> Basics.Int"},{"name":"toBytes","comment":" Extract the content of a `File` as `Bytes`. So if you have an `archive.zip`\nfile you could read the content like this:\n\n    import Bytes exposing (Bytes)\n    import File exposing (File)\n    import Task\n\n    type Msg\n        = ZipLoaded Bytes\n\n    read : File -> Cmd Msg\n    read file =\n        Task.perform ZipLoaded (File.toBytes file)\n\nFrom here you can use the [`elm/bytes`](/packages/elm/bytes/latest) package to\nwork with the bytes and turn them into whatever you want.\n\n","type":"Effect.File.File -> Effect.Internal.Task Effect.Command.FrontendOnly x Bytes.Bytes"},{"name":"toInternalFile","comment":" Please ignore\n","type":"Effect.File.File -> Effect.Internal.File"},{"name":"toString","comment":" Extract the content of a `File` as a `String`. So if you have a `notes.md`\nfile you could read the content like this:\n\n    import File exposing (File)\n    import Task\n\n    type Msg\n        = MarkdownLoaded String\n\n    read : File -> Cmd Msg\n    read file =\n        Task.perform MarkdownLoaded (File.toString file)\n\nReading the content is asynchronous because browsers want to avoid allocating\nthe file content into memory if possible. (E.g. if you are just sending files\nalong to a server with [`elm/http`](/packages/elm/http/latest) there is no\npoint having their content in memory!)\n\n","type":"Effect.File.File -> Effect.Internal.Task Effect.Command.FrontendOnly x String.String"},{"name":"toUrl","comment":" The `File.toUrl` function will convert files into URLs like this:\n\n  - `data:*/*;base64,V2hvIGF0ZSBhbGwgdGhlIHBpZT8=`\n  - `data:*/*;base64,SXQgd2FzIG1lLCBXaWxleQ==`\n  - `data:*/*;base64,SGUgYXRlIGFsbCB0aGUgcGllcywgYm95IQ==`\n\nThis is using a [Base64](https://en.wikipedia.org/wiki/Base64) encoding to\nturn arbitrary binary data into ASCII characters that safely fit in strings.\n\nThis is primarily useful when you want to show images that were just uploaded\nbecause **an `<img>` tag expects its `src` attribute to be a URL.** So if you\nhave a website for selling furniture, using `File.toUrl` could make it easier\nto create a screen to preview and reorder images. This way people can make\nsure their old table looks great!\n\n","type":"Effect.File.File -> Effect.Internal.Task Effect.Command.FrontendOnly x String.String"}],"binops":[]},{"name":"Effect.File.Download","comment":" Commands for downloading files.\n\n**SECURITY NOTE:** Browsers require that all downloads are initiated by a user\nevent. So rather than allowing malicious sites to put files on your computer\nhowever they please, the user at least have to click a button first. As a\nresult, the following commands only work when they are triggered by some user\nevent.\n\n\n# Download\n\n@docs string, bytes, url\n\n","unions":[],"aliases":[],"values":[{"name":"bytes","comment":" Download some `Bytes` as a file. Maybe you are creating custom images,\nand you want a button to download them as PNG files. After using\n[`elm/bytes`][bytes] to generate the file content, you can download it like\nthis:\n\n    import Bytes exposing (Bytes)\n    import File.Download as Download\n\n    savePng : Bytes -> Cmd msg\n    savePng bytes =\n        Download.bytes \"frog.png\" \"image/png\" bytes\n\nSo the arguments are file name, MIME type, and then the file content. With the\nability to build any byte sequence you want with [`elm/bytes`][bytes], you can\ncreate `.zip` files, `.jpg` files, or whatever else you might need!\n\n[bytes]: /packages/elm/bytes/latest\n\n","type":"String.String -> String.String -> Bytes.Bytes -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"string","comment":" Download a `String` as a file. Maybe you markdown editor in the browser,\nand you want to provide a button to download markdown files:\n\n    import File.Download as Download\n\n    save : String -> Cmd msg\n    save markdown =\n        Download.string \"draft.md\" \"text/markdown\" markdown\n\nSo the arguments are file name, MIME type, and then the file content. In this\ncase is is markdown, but it could be any string information.\n\n","type":"String.String -> String.String -> String.String -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"url","comment":" Download a file from a URL on the same origin. So if you have a website\nat `https://example.com`, you could download a math GIF like this:\n\n    import File.Download as Download\n\n    downloadMathGif : Cmd msg\n    downloadMathGif =\n        Download.url \"https://example.com/math.gif\"\n\nThe downloaded file will use whatever name the server suggests. So if you want\na different name, have your server add a [`Content-Disposition`][cd] header like\n`Content-Disposition: attachment; filename=\"triangle.gif\"` when it serves the\nfile.\n\n**Warning:** The implementation uses `<a href=\"...\" download></a>` which has\ntwo important consequences:\n\n1.  **Cross-origin downloads are weird.** If you want a file from a different\n    domain (like `https://files.example.com` or `https://www.wikipedia.org`) this\n    function adds a `target=\"_blank\"`, opening the file in a new tab. Otherwise\n    the link would just take over the current page, replacing your website with a\n    GIF or whatever. To make cross-origin downloads work differently, you can (1)\n    make the request same-origin by sending it to your server and then having your\n    server fetch the file or (2) fetch the file with `elm/http` and then go through\n    `File.Download.bytes`.\n2.  **Same-origin downloads are weird in IE10 and IE11.** These browsers do not\n    support the `download` attribute, so you should always get the `target=\"_blank\"`\n    behavior where the URL opens in a new tab. Again, you can fetch the file with\n    `elm/http` and then use `File.Download.bytes` to get around this.\n\nThings are quite tricky here between the intentional security constraints and\nparticularities of browser implementations, so remember that you can always\nsend the URL out a `port` and do something even more custom in JavaScript!\n\n[cd]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition\n\n","type":"String.String -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"}],"binops":[]},{"name":"Effect.File.Select","comment":" Ask the user to select some files.\n\n**SECURITY NOTE:** Browsers will only open a file selector in reaction to a\nuser event. So rather than allowing malicious sites to ask for files whenever\nthey please, the user at least have to click a button first. As a result, the\nfollowing commands only work when they are triggered by some user event.\n\n\n# Select Files\n\n@docs file, files\n\n\n# Limitations\n\nThe API here uses commands, but it seems like it could also provide tasks.\nThe trouble is that a `Task` is guaranteed to succeed or fail. There should\nnot be any cases where it just does neither. File selection makes this tricky\nbecause there are two limitations in JavaScript as of this writing:\n\n1.  File selection must be a direct response to a user event. This is intended\n    to help with security. It is not clear how to reliably detect when these\n    commands were issued at invalid times, especially across browsers.\n2.  The user can always click `Cancel` on the file dialog. It is quite\n    difficult to reliably detect if someone has clicked this button across\n    browsers, especially when it is hard to know if the dialog is even open in the\n    first place.\n\nI think it would be worth figuring out how to know these two things reliably\nbefore exposing a `Task` API for things.\n\n","unions":[],"aliases":[],"values":[{"name":"file","comment":" Ask the user to select **one** file. To ask for a single `.zip` file you\ncould say:\n\n    import File.Select as Select\n\n    type Msg\n        = ZipRequested\n        | ZipLoaded File\n\n    requestZip : Cmd Msg\n    requestZip =\n        Select.file [ \"application/zip\" ] ZipLoaded\n\nYou provide (1) a list of acceptable MIME types and (2) a function to turn the\nresulting file into a message for your `update` function. In this case, we only\nwant files with MIME type `application/zip`.\n\n**Note:** This only works when the command is the direct result of a user\nevent, like clicking something.\n\n**Note:** This command may not resolve, partly because it is unclear how to\nreliably detect `Cancel` clicks across browsers. More about that in the\nsection on [limitations](#limitations) below.\n\n","type":"List.List String.String -> (Effect.File.File -> msg) -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"},{"name":"files","comment":" Ask the user to select **one or more** files. To ask for many image files,\nyou could say:\n\n    import File.Select as Select\n\n    type Msg\n        = ImagesRequested\n        | ImagesLoaded File (List File)\n\n    requestImages : Cmd Msg\n    requestImages =\n        Select.files [ \"image/png\", \"image/jpg\" ] ImagesLoaded\n\nIn this case, we only want PNG and JPG files.\n\nNotice that the function that turns the resulting files into a message takes\ntwo arguments: the first file selected and then a list of the other selected\nfiles. This guarantees that one file (or more) is available. This way you do\nnot have to handle “no files loaded” in your code. That can never happen!\n\n**Note:** This only works when the command is the direct result of a user\nevent, like clicking something.\n\n**Note:** This command may not resolve, partly because it is unclear how to\nreliably detect `Cancel` clicks across browsers. More about that in the\nsection on [limitations](#limitations) below.\n\n","type":"List.List String.String -> (Effect.File.File -> List.List Effect.File.File -> msg) -> Effect.Command.Command Effect.Command.FrontendOnly toMsg msg"}],"binops":[]},{"name":"Effect.Http","comment":" Send HTTP requests.\n\n\n# Requests\n\n@docs get, post, request\n\n\n# Header\n\n@docs Header, header\n\n\n# Body\n\n@docs Body, emptyBody, stringBody, jsonBody, fileBody, bytesBody\n\n\n# Body Parts\n\n@docs multipartBody, Part, stringPart, filePart, bytesPart\n\n\n# Expect\n\n@docs Expect, expectString, expectJson, expectBytes, expectWhatever, Error\n\n\n# Progress\n\n@docs track, Progress, fractionSent, fractionReceived\n\n\n# Cancel\n\n@docs cancel\n\n\n# Risky Requests\n\n@docs riskyRequest\n\n\n# Elaborate Expectations\n\n@docs expectStringResponse, expectBytesResponse, Response, Metadata\n\n\n# Tasks\n\n@docs task, Resolver, stringResolver, bytesResolver, riskyTask\n\n","unions":[{"name":"Error","comment":" A `Request` can fail in a couple ways:\n\n  - `BadUrl` means you did not provide a valid URL.\n  - `Timeout` means it took too long to get a response.\n  - `NetworkError` means the user turned off their wifi, went in a cave, etc.\n  - `BadStatus` means you got a response back, but the status code indicates failure.\n  - `BadBody` means you got a response back with a nice status code, but the body\n    of the response was something unexpected. The `String` in this case is a\n    debugging message that explains what went wrong with your JSON decoder or\n    whatever.\n\n**Note:** You can use [`expectStringResponse`](#expectStringResponse) and\n[`expectBytesResponse`](#expectBytesResponse) to get more flexibility on this.\n\n","args":[],"cases":[["BadUrl",["String.String"]],["Timeout",[]],["NetworkError",[]],["BadStatus",["Basics.Int"]],["BadBody",["String.String"]]]},{"name":"Expect","comment":" Logic for interpreting a response body.\n","args":["msg"],"cases":[]},{"name":"Progress","comment":" There are two phases to HTTP requests. First you **send** a bunch of data,\nthen you **receive** a bunch of data. For example, say you use `fileBody` to\nupload a file of 262144 bytes. From there, progress will go like this:\n\n    Sending { sent = 0, size = 262144 } -- 0.0\n\n    Sending { sent = 65536, size = 262144 } -- 0.25\n\n    Sending { sent = 131072, size = 262144 } -- 0.5\n\n    Sending { sent = 196608, size = 262144 } -- 0.75\n\n    Sending { sent = 262144, size = 262144 } -- 1.0\n\n    Receiving { received = 0, size = Just 16 } -- 0.0\n\n    Receiving { received = 16, size = Just 16 } -- 1.0\n\nWith file uploads, the **send** phase is expensive. That is what we saw in our\nexample. But with file downloads, the **receive** phase is expensive.\n\nUse [`fractionSent`](#fractionSent) and [`fractionReceived`](#fractionReceived)\nto turn this progress information into specific fractions!\n\n**Note:** The `size` of the response is based on the [`Content-Length`][cl]\nheader, and in rare and annoying cases, a server may not include that header.\nThat is why the `size` is a `Maybe Int` in `Receiving`.\n\n[cl]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length\n\n","args":[],"cases":[["Sending",["{ sent : Basics.Int, size : Basics.Int }"]],["Receiving",["{ received : Basics.Int, size : Maybe.Maybe Basics.Int }"]]]},{"name":"Resolver","comment":" Describes how to resolve an HTTP task.\n","args":["restriction","x","a"],"cases":[]},{"name":"Response","comment":" A `Response` can come back a couple different ways:\n\n  - `BadUrl_` means you did not provide a valid URL.\n  - `Timeout_` means it took too long to get a response.\n  - `NetworkError_` means the user turned off their wifi, went in a cave, etc.\n  - `BadResponse_` means you got a response back, but the status code indicates failure.\n  - `GoodResponse_` means you got a response back with a nice status code!\n\nThe type of the `body` depends on whether you use\n[`expectStringResponse`](#expectStringResponse)\nor [`expectBytesResponse`](#expectBytesResponse).\n\n","args":["body"],"cases":[["BadUrl_",["String.String"]],["Timeout_",[]],["NetworkError_",[]],["BadStatus_",["Effect.Http.Metadata","body"]],["GoodStatus_",["Effect.Http.Metadata","body"]]]}],"aliases":[{"name":"Body","comment":" Represents the body of a `Request`.\n","args":[],"type":"Effect.Internal.HttpBody"},{"name":"Header","comment":" An HTTP header for configuring requests.\n","args":[],"type":"( String.String, String.String )"},{"name":"Metadata","comment":" Extra information about the response:\n\n  - `url` of the server that actually responded (so you can detect redirects)\n  - `statusCode` like `200` or `404`\n  - `statusText` describing what the `statusCode` means a little\n  - `headers` like `Content-Length` and `Expires`\n\n**Note:** It is possible for a response to have the same header multiple times.\nIn that case, all the values end up in a single entry in the `headers`\ndictionary. The values are separated by commas, following the rules outlined\n[here](https://stackoverflow.com/questions/4371328/are-duplicate-http-response-headers-acceptable).\n\n","args":[],"type":"{ url : String.String, statusCode : Basics.Int, statusText : String.String, headers : Dict.Dict String.String String.String }"},{"name":"Part","comment":" One part of a `multipartBody`.\n","args":[],"type":"Effect.Internal.HttpPart"}],"values":[{"name":"bytesBody","comment":" Put some `Bytes` in the body of your `Request`. This allows you to use\n[`elm/bytes`](/packages/elm/bytes/latest) to have full control over the binary\nrepresentation of the data you are sending. For example, you could create an\n`archive.zip` file and send it along like this:\n\n    import Bytes exposing (Bytes)\n\n    zipBody : Bytes -> Body\n    zipBody bytes =\n        bytesBody \"application/zip\" bytes\n\nThe first argument is a [MIME type](https://en.wikipedia.org/wiki/Media_type)\nof the body. In other scenarios you may want to use MIME types like `image/png`\nor `image/jpeg` instead.\n\n**Note:** Use [`track`](#track) to track upload progress.\n\n","type":"String.String -> Bytes.Bytes -> Effect.Http.Body"},{"name":"bytesPart","comment":" A part that contains bytes, allowing you to use\n[`elm/bytes`](/packages/elm/bytes/latest) to encode data exactly in the format\nyou need.\n\n    multipartBody\n        [ stringPart \"title\" \"Tom\"\n        , bytesPart \"photo\" \"image/png\" bytes\n        ]\n\n**Note:** You must provide a MIME type so that the receiver has clues about\nhow to interpret the bytes.\n\n","type":"String.String -> String.String -> Bytes.Bytes -> Effect.Http.Part"},{"name":"bytesResolver","comment":" Turn a response with a `Bytes` body into a result.\nSimilar to [`expectBytesResponse`](#expectBytesResponse).\n","type":"(Effect.Http.Response Bytes.Bytes -> Result.Result x a) -> Effect.Http.Resolver restriction x a"},{"name":"cancel","comment":" Try to cancel an ongoing request based on a `tracker`.\n","type":"String.String -> Effect.Command.Command restriction toMsg msg"},{"name":"emptyBody","comment":" Create an empty body for your `Request`.\n","type":"Effect.Http.Body"},{"name":"expectBytes","comment":" Expect the response body to be binary data. For example, maybe you are\ntalking to an endpoint that gives back ProtoBuf data:\n\n    import Bytes.Decode as Bytes\n    import Http\n\n    type Msg\n        = GotData (Result Http.Error Data)\n\n    getData : Cmd Msg\n    getData =\n        Http.get\n            { url = \"/data\"\n            , expect = Http.expectBytes GotData dataDecoder\n            }\n\n    -- dataDecoder : Bytes.Decoder Data\n\nYou would use [`elm/bytes`](/packages/elm/bytes/latest/) to decode the binary\ndata according to a proto definition file like `example.proto`.\n\nIf the decoder fails, you get a `BadBody` error that just indicates that\n_something_ went wrong. It probably makes sense to debug by peeking at the\nbytes you are getting in the browser developer tools or something.\n\n","type":"(Result.Result Effect.Http.Error a -> msg) -> Bytes.Decode.Decoder a -> Effect.Http.Expect msg"},{"name":"expectBytesResponse","comment":" Expect a [`Response`](#Response) with a `Bytes` body.\n\nIt works just like [`expectStringResponse`](#expectStringResponse), giving you\nmore access to headers and more leeway in defining your own errors.\n\n","type":"(Result.Result x a -> msg) -> (Effect.Http.Response Bytes.Bytes -> Result.Result x a) -> Effect.Http.Expect msg"},{"name":"expectJson","comment":" Expect the response body to be JSON.\n","type":"(Result.Result Effect.Http.Error a -> msg) -> Json.Decode.Decoder a -> Effect.Http.Expect msg"},{"name":"expectString","comment":" Expect the response body to be a `String`.\n","type":"(Result.Result Effect.Http.Error String.String -> msg) -> Effect.Http.Expect msg"},{"name":"expectStringResponse","comment":" Expect a Response with a String body.\n","type":"(Result.Result x a -> msg) -> (Effect.Http.Response String.String -> Result.Result x a) -> Effect.Http.Expect msg"},{"name":"expectWhatever","comment":" Expect the response body to be whatever.\n","type":"(Result.Result Effect.Http.Error () -> msg) -> Effect.Http.Expect msg"},{"name":"fileBody","comment":" Use a file as the body of your `Request`. When someone uploads an image\ninto the browser with [`elm/file`](/packages/elm/file/latest) you can forward\nit to a server.\n\nThis will automatically set the `Content-Type` to the MIME type of the file.\n\n**Note:** Use [`track`](#track) to track upload progress.\n\n","type":"Effect.File.File -> Effect.Http.Body"},{"name":"filePart","comment":" A part that contains a file. You can use\n[`elm/file`](/packages/elm/file/latest) to get files loaded into the\nbrowser. From there, you can send it along to a server like this:\n\n    multipartBody\n        [ stringPart \"product\" \"Ikea Bekant\"\n        , stringPart \"description\" \"Great desk for home office.\"\n        , filePart \"image[]\" file1\n        , filePart \"image[]\" file2\n        , filePart \"image[]\" file3\n        ]\n\n","type":"String.String -> Effect.File.File -> Effect.Http.Part"},{"name":"fractionReceived","comment":" Turn `Receiving` progress into a useful fraction for progress bars.\n\n    fractionReceived { received =   0, size = Just 1024 } == 0.0\n    fractionReceived { received = 256, size = Just 1024 } == 0.25\n    fractionReceived { received = 512, size = Just 1024 } == 0.5\n\n    -- fractionReceived { received =   0, size = Nothing } == 0.0\n    -- fractionReceived { received = 256, size = Nothing } == 0.0\n    -- fractionReceived { received = 512, size = Nothing } == 0.0\n\nThe `size` here is based on the [`Content-Length`][cl] header which may be\nmissing in some cases. A server may be misconfigured or it may be streaming\ndata and not actually know the final size. Whatever the case, this function\nwill always give `0.0` when the final size is unknown.\n\nFurthermore, the `Content-Length` header may be incorrect! The implementation\nclamps the fraction between `0.0` and `1.0`, so you will just get `1.0` if\nyou ever receive more bytes than promised.\n\n**Note:** If you are streaming something, you can write a custom version of\nthis function that just tracks bytes received. Maybe you show that 22kb or 83kb\nhave been downloaded, without a specific fraction. If you do this, be wary of\ndivide-by-zero errors because `size` can always be zero!\n\n[cl]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length\n\n","type":"{ received : Basics.Int, size : Maybe.Maybe Basics.Int } -> Basics.Float"},{"name":"fractionSent","comment":" Turn `Sending` progress into a useful fraction.\n\n    fractionSent { sent =   0, size = 1024 } == 0.0\n    fractionSent { sent = 256, size = 1024 } == 0.25\n    fractionSent { sent = 512, size = 1024 } == 0.5\n\n    -- fractionSent { sent = 0, size = 0 } == 1.0\n\nThe result is always between `0.0` and `1.0`, ensuring that any progress bar\nanimations never go out of bounds.\n\nAnd notice that `size` can be zero. That means you are sending a request with\nan empty body. Very common! When `size` is zero, the result is always `1.0`.\n\n**Note:** If you create your own function to compute this fraction, watch out\nfor divide-by-zero errors!\n\n","type":"{ sent : Basics.Int, size : Basics.Int } -> Basics.Float"},{"name":"get","comment":" Create a `GET` request.\n","type":"{ url : String.String, expect : Effect.Http.Expect msg } -> Effect.Command.Command restriction toFrontend msg"},{"name":"header","comment":" Create a `Header`.\n","type":"String.String -> String.String -> Effect.Http.Header"},{"name":"jsonBody","comment":" Put some JSON value in the body of your `Request`. This will automatically\nadd the `Content-Type: application/json` header.\n","type":"Json.Encode.Value -> Effect.Http.Body"},{"name":"multipartBody","comment":" When someone clicks submit on the `<form>`, browsers send a special HTTP\nrequest with all the form data. Something like this:\n\n    POST /test.html HTTP/1.1\n    Host: example.org\n    Content-Type: multipart/form-data;boundary=\"7MA4YWxkTrZu0gW\"\n\n    --7MA4YWxkTrZu0gW\n    Content-Disposition: form-data; name=\"title\"\n\n    Trip to London\n    --7MA4YWxkTrZu0gW\n    Content-Disposition: form-data; name=\"album[]\"; filename=\"parliment.jpg\"\n\n    ...RAW...IMAGE...BITS...\n    --7MA4YWxkTrZu0gW--\n\nThis was the only way to send files for a long time, so many servers expect\ndata in this format. **The `multipartBody` function lets you create these\nrequests.** For example, to upload a photo album all at once, you could create\na body like this:\n\n    multipartBody\n        [ stringPart \"title\" \"Trip to London\"\n        , filePart \"album[]\" file1\n        , filePart \"album[]\" file2\n        , filePart \"album[]\" file3\n        ]\n\nAll of the body parts need to have a name. Names can be repeated. Adding the\n`[]` on repeated names is a convention from PHP. It seems weird, but I see it\nenough to mention it. You do not have to do it that way, especially if your\nserver uses some other convention!\n\nThe `Content-Type: multipart/form-data` header is automatically set when\ncreating a body this way.\n\n**Note:** Use [`track`](#track) to track upload progress.\n\n","type":"List.List Effect.Http.Part -> Effect.Http.Body"},{"name":"post","comment":" Create a `POST` request.\n","type":"{ url : String.String, body : Effect.Http.Body, expect : Effect.Http.Expect msg } -> Effect.Command.Command restriction toFrontend msg"},{"name":"request","comment":" Create a custom request.\n","type":"{ method : String.String, headers : List.List Effect.Http.Header, url : String.String, body : Effect.Http.Body, expect : Effect.Http.Expect msg, timeout : Maybe.Maybe Duration.Duration, tracker : Maybe.Maybe String.String } -> Effect.Command.Command restriction toFrontend msg"},{"name":"riskyRequest","comment":" Create a request with a risky security policy. Things like:\n\n  - Allow responses from other domains to set cookies.\n  - Include cookies in requests to other domains.\n\nThis is called [`withCredentials`][wc] in JavaScript, and it allows a couple\nother risky things as well. It can be useful if `www.example.com` needs to\ntalk to `uploads.example.com`, but it should be used very carefully!\n\nFor example, every HTTP request includes a `Host` header revealing the domain,\nso any request to `facebook.com` reveals the website that sent it. From there,\ncookies can be used to correlate browsing habits with specific users. “Oh, it\nlooks like they visited `example.com`. Maybe they want ads about examples!”\nThis is why you can get shoe ads for months without saying anything about it\non any social networks. **This risk exists even for people who do not have an\naccount.** Servers can set a new cookie to uniquely identify the browser and\nbuild a profile around that. Same kind of tricks for logged out users.\n\n**Context:** A significantly worse version of this can happen when trying to\nadd integrations with Google, Facebook, Pinterest, Twitter, etc. “Add our share\nbutton. It is super easy. Just add this `<script>` tag!” But the goal here is\nto get _arbitrary_ access to the executing context. Now they can track clicks,\nread page content, use time zones to approximate location, etc. As of this\nwriting, suggesting that developers just embed `<script>` tags is the default\nfor Google Analytics, Facebook Like Buttons, Twitter Follow Buttons, Pinterest\nSave Buttons, and Instagram Embeds.\n\n[ah]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization\n[wc]: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials\n\n","type":"{ method : String.String, headers : List.List Effect.Http.Header, url : String.String, body : Effect.Http.Body, expect : Effect.Http.Expect msg, timeout : Maybe.Maybe Duration.Duration, tracker : Maybe.Maybe String.String } -> Effect.Command.Command restriction toMsg msg"},{"name":"riskyTask","comment":" Just like [`riskyRequest`](#riskyRequest), but it creates a `Task`. **Use\nwith caution!** This has all the same security concerns as `riskyRequest`.\n","type":"{ method : String.String, headers : List.List Effect.Http.Header, url : String.String, body : Effect.Http.Body, resolver : Effect.Http.Resolver restriction x a, timeout : Maybe.Maybe Duration.Duration } -> Effect.Task.Task restriction x a"},{"name":"stringBody","comment":" Put some string in the body of your `Request`.\n","type":"String.String -> String.String -> Effect.Http.Body"},{"name":"stringPart","comment":" A part that contains `String` data.\n\n    multipartBody\n        [ stringPart \"title\" \"Tom\"\n        , filePart \"photo\" tomPng\n        ]\n\n","type":"String.String -> String.String -> Effect.Http.Part"},{"name":"stringResolver","comment":" Turn a response with a `String` body into a result.\n","type":"(Effect.Http.Response String.String -> Result.Result x a) -> Effect.Http.Resolver restriction x a"},{"name":"task","comment":" Just like [`request`](#request), but it creates a `Task`.\n","type":"{ method : String.String, headers : List.List Effect.Http.Header, url : String.String, body : Effect.Http.Body, resolver : Effect.Http.Resolver restriction x a, timeout : Maybe.Maybe Duration.Duration } -> Effect.Task.Task restriction x a"},{"name":"track","comment":" Track the progress of a request. Create a [`request`](#request) where\n`tracker = Just \"form.pdf\"` and you can track it with a subscription like\n`track \"form.pdf\" GotProgress`.\n","type":"String.String -> (Effect.Http.Progress -> msg) -> Effect.Subscription.Subscription restriction msg"}],"binops":[]},{"name":"Effect.Lamdera","comment":" backend\n\n@docs frontend, backend, sendToBackend, sendToFrontend, sendToFrontends, broadcast, onConnect, onDisconnect, ClientId, clientIdToString, clientIdFromString, SessionId, sessionIdToString, sessionIdFromString\n\n\n# Temporary integration\n\n@docs toCmd\n\n","unions":[{"name":"ClientId","comment":" ","args":[],"cases":[]},{"name":"SessionId","comment":" ","args":[],"cases":[]}],"aliases":[],"values":[{"name":"backend","comment":" Create a Lamdera backend application\n","type":"(toFrontend -> Platform.Cmd.Cmd backendMsg) -> (String.String -> toFrontend -> Platform.Cmd.Cmd backendMsg) -> { init : ( backendModel, Effect.Command.Command Effect.Command.BackendOnly toFrontend backendMsg ), update : backendMsg -> backendModel -> ( backendModel, Effect.Command.Command Effect.Command.BackendOnly toFrontend backendMsg ), updateFromFrontend : Effect.Lamdera.SessionId -> Effect.Lamdera.ClientId -> toBackend -> backendModel -> ( backendModel, Effect.Command.Command Effect.Command.BackendOnly toFrontend backendMsg ), subscriptions : backendModel -> Effect.Subscription.Subscription Effect.Command.BackendOnly backendMsg } -> { init : ( backendModel, Platform.Cmd.Cmd backendMsg ), update : backendMsg -> backendModel -> ( backendModel, Platform.Cmd.Cmd backendMsg ), updateFromFrontend : String.String -> String.String -> toBackend -> backendModel -> ( backendModel, Platform.Cmd.Cmd backendMsg ), subscriptions : backendModel -> Platform.Sub.Sub backendMsg }"},{"name":"broadcast","comment":" Send a toFrontend msg to all currently connected clients\n","type":"toFrontend -> Effect.Command.Command Effect.Command.BackendOnly toFrontend backendMsg"},{"name":"clientIdFromString","comment":" ","type":"String.String -> Effect.Lamdera.ClientId"},{"name":"clientIdToString","comment":" ","type":"Effect.Lamdera.ClientId -> String.String"},{"name":"frontend","comment":" Create a Lamdera frontend application\n","type":"(toBackend -> Platform.Cmd.Cmd frontendMsg) -> { init : Url.Url -> Effect.Browser.Navigation.Key -> ( model, Effect.Command.Command Effect.Command.FrontendOnly toBackend frontendMsg ), view : model -> Browser.Document frontendMsg, update : frontendMsg -> model -> ( model, Effect.Command.Command Effect.Command.FrontendOnly toBackend frontendMsg ), updateFromBackend : toFrontend -> model -> ( model, Effect.Command.Command Effect.Command.FrontendOnly toBackend frontendMsg ), subscriptions : model -> Effect.Subscription.Subscription Effect.Command.FrontendOnly frontendMsg, onUrlRequest : Browser.UrlRequest -> frontendMsg, onUrlChange : Url.Url -> frontendMsg } -> { init : Url.Url -> Browser.Navigation.Key -> ( model, Platform.Cmd.Cmd frontendMsg ), view : model -> Browser.Document frontendMsg, update : frontendMsg -> model -> ( model, Platform.Cmd.Cmd frontendMsg ), updateFromBackend : toFrontend -> model -> ( model, Platform.Cmd.Cmd frontendMsg ), subscriptions : model -> Platform.Sub.Sub frontendMsg, onUrlRequest : Browser.UrlRequest -> frontendMsg, onUrlChange : Url.Url -> frontendMsg }"},{"name":"onConnect","comment":" Subscribe to Frontend client connected events\n","type":"(Effect.Lamdera.SessionId -> Effect.Lamdera.ClientId -> backendMsg) -> Effect.Subscription.Subscription Effect.Command.BackendOnly backendMsg"},{"name":"onDisconnect","comment":" Subscribe to Frontend client disconnected events\n","type":"(Effect.Lamdera.SessionId -> Effect.Lamdera.ClientId -> backendMsg) -> Effect.Subscription.Subscription Effect.Command.BackendOnly backendMsg"},{"name":"sendToBackend","comment":" Send a toBackend msg to the Backend\n","type":"toBackend -> Effect.Command.Command Effect.Command.FrontendOnly toBackend frontendMsg"},{"name":"sendToFrontend","comment":" Send a toFrontend msg to the Frontend\n","type":"Effect.Lamdera.ClientId -> toFrontend -> Effect.Command.Command Effect.Command.BackendOnly toFrontend backendMsg"},{"name":"sendToFrontends","comment":" Send a toFrontend msg to all the frontends that have a given SessionId.\n","type":"Effect.Lamdera.SessionId -> toFrontend -> Effect.Command.Command Effect.Command.BackendOnly toFrontend backendMsg"},{"name":"sessionIdFromString","comment":" ","type":"String.String -> Effect.Lamdera.SessionId"},{"name":"sessionIdToString","comment":" ","type":"Effect.Lamdera.SessionId -> String.String"},{"name":"toCmd","comment":" Escape hatch for converting a `Command` to a regular `Cmd` in non-test code.\n","type":"(toMsg -> Platform.Cmd.Cmd msg) -> (String.String -> toMsg -> Platform.Cmd.Cmd msg) -> (toMsg -> Platform.Cmd.Cmd msg) -> Effect.Command.Command restriction toMsg msg -> Platform.Cmd.Cmd msg"}],"binops":[]},{"name":"Effect.LocalDev","comment":" Ignore this module, for internal use only.\n\n@docs DevBar, InitConfig, Model, Msg, SubscriptionsConfig, UpdateConfig, ViewConfig, fileReadWriteErrorView, hideFreezeAndResetButtons, init, initDevBar, isFullyInitialized, maybeTestEditorView, onConnection, onDisconnection, receivedToFrontend, recordingButton, recordingPill, resetDebugStoreBE, subscriptions, update\n\n","unions":[{"name":"Model","comment":" ","args":["msg"],"cases":[]},{"name":"Msg","comment":" ","args":[],"cases":[]}],"aliases":[{"name":"DevBar","comment":" ","args":[],"type":"{ isRecordingEvents : Maybe.Maybe Effect.LocalDev.RecordingState }"},{"name":"InitConfig","comment":" ","args":["msg"],"type":"{ clientId : Lamdera.ClientId, devBar : Effect.LocalDev.DevBar, initCmds : Platform.Cmd.Cmd msg, isLeader : Basics.Bool, mapMsg : Effect.LocalDev.Msg -> msg, sendToFrontend : Effect.LocalDev.WireMsg -> Platform.Cmd.Cmd msg, sessionId : Lamdera.SessionId, startRecording : () -> Platform.Cmd.Cmd msg }"},{"name":"SubscriptionsConfig","comment":" ","args":["msg"],"type":"{ devBar : Effect.LocalDev.DevBar, gotEvent : (Lamdera.Json.Value -> msg) -> Platform.Sub.Sub msg, mapMsg : Effect.LocalDev.Msg -> msg, receiveToFrontend : Platform.Sub.Sub msg }"},{"name":"UpdateConfig","comment":" ","args":["msg","model"],"type":"{ clientId : Lamdera.ClientId, copyToClipboard : String.String -> Platform.Cmd.Cmd msg, debugSaveDevBar : model -> model, devBar : Effect.LocalDev.DevBar, isLeader : Basics.Bool, mapMsg : Effect.LocalDev.Msg -> msg, onConnection : Effect.LocalDev.ConnectionMsg -> Platform.Cmd.Cmd msg, originalUrl : Lamdera.Url, resetBackend : model -> ( model, Platform.Cmd.Cmd msg ), sendToFrontend : Effect.LocalDev.WireMsg -> Platform.Cmd.Cmd msg, sessionId : Lamdera.SessionId, setDevBar : Effect.LocalDev.DevBar -> model -> model, setExpanded : Basics.Bool -> model -> model, setFreeze : Basics.Bool -> model -> model, setModel : Effect.LocalDev.Model msg -> model -> model, startRecording : () -> Platform.Cmd.Cmd msg, stopRecording : () -> Platform.Cmd.Cmd msg }"},{"name":"ViewConfig","comment":" ","args":[],"type":"{ charcoal : String.String, grey : String.String, white : String.String }"}],"values":[{"name":"fileReadWriteErrorView","comment":" ","type":"Effect.LocalDev.ViewConfig -> Effect.LocalDev.Model msg -> List.List (Html.Html Effect.LocalDev.Msg)"},{"name":"hideFreezeAndResetButtons","comment":" ","type":"Effect.LocalDev.DevBar -> Basics.Bool"},{"name":"init","comment":" ","type":"Effect.LocalDev.InitConfig msg -> ( Effect.LocalDev.Model msg, Platform.Cmd.Cmd msg )"},{"name":"initDevBar","comment":" ","type":"Effect.LocalDev.DevBar"},{"name":"isFullyInitialized","comment":" ","type":"Effect.LocalDev.Model msg -> Basics.Bool"},{"name":"maybeTestEditorView","comment":" ","type":"Effect.LocalDev.ViewConfig -> Effect.LocalDev.DevBar -> Effect.LocalDev.Model msg -> Maybe.Maybe (List.List (Html.Html Effect.LocalDev.Msg))"},{"name":"onConnection","comment":" ","type":"Effect.LocalDev.UpdateConfig msg model -> Effect.LocalDev.ConnectionMsg -> Effect.LocalDev.Model msg -> (model -> ( model, Platform.Cmd.Cmd msg )) -> model -> ( model, Platform.Cmd.Cmd msg )"},{"name":"onDisconnection","comment":" ","type":"Effect.LocalDev.UpdateConfig msg model -> Effect.LocalDev.ConnectionMsg -> Effect.LocalDev.Model msg -> (model -> ( model, Platform.Cmd.Cmd msg )) -> model -> ( model, Platform.Cmd.Cmd msg )"},{"name":"receivedToFrontend","comment":" ","type":"Effect.LocalDev.UpdateConfig msg model -> Effect.LocalDev.WireMsg -> Effect.LocalDev.Model msg -> (model -> ( model, Platform.Cmd.Cmd msg )) -> model -> ( model, Platform.Cmd.Cmd msg )"},{"name":"recordingButton","comment":" ","type":"Effect.LocalDev.DevBar -> (Effect.LocalDev.Msg -> Html.Html msg) -> (Effect.LocalDev.Msg -> Html.Html msg) -> Html.Html msg"},{"name":"recordingPill","comment":" ","type":"Effect.LocalDev.DevBar -> Maybe.Maybe Effect.LocalDev.Msg"},{"name":"resetDebugStoreBE","comment":" ","type":"Effect.LocalDev.UpdateConfig msg model -> model -> model"},{"name":"subscriptions","comment":" ","type":"Effect.LocalDev.SubscriptionsConfig msg -> Effect.LocalDev.Model msg -> Platform.Sub.Sub msg"},{"name":"update","comment":" ","type":"Effect.LocalDev.UpdateConfig msg model -> Effect.LocalDev.Msg -> Effect.LocalDev.Model msg -> model -> ( model, Platform.Cmd.Cmd msg )"}],"binops":[]},{"name":"Effect.Process","comment":"\n\n\n# Processes\n\n@docs sleep\n\n","unions":[],"aliases":[],"values":[{"name":"sleep","comment":" Block progress on the current process for the given number of milliseconds.\nThe JavaScript equivalent of this is [`setTimeout`][setTimeout] which lets you\ndelay work until later.\n\n[setTimeout]: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout\n\n","type":"Duration.Duration -> Effect.Task.Task restriction x ()"}],"binops":[]},{"name":"Effect.Snapshot","comment":" Upload snapshots to Percy.io for visual regression testing.\nYou'll need to create an account first in order to get an API key.\n\n@docs uploadSnapshots, PercyApiKey, Snapshot, PublicFile, Response, Error, errorToString\n\n","unions":[{"name":"Error","comment":" Possible errors when uploading snapshots.\n","args":[],"cases":[["BadUrl",["String.String"]],["Timeout",[]],["NetworkError",[]],["BadStatus",["{ statusCode : Basics.Int, body : String.String }"]],["BadBody",["String.String"]],["SnapshotNamesNotUnique",[]]]},{"name":"PercyApiKey","comment":" An API key needed to upload snapshots to Percy.io. Create an account first in order to get an API key.\n","args":[],"cases":[["PercyApiKey",["String.String"]]]}],"aliases":[{"name":"PublicFile","comment":" Files in your public folder such as `images/profile-image.png` or `favicon.ico`.\n","args":[],"type":"{ filepath : String.String, content : Bytes.Bytes }"},{"name":"Response","comment":" Response from server after we upload snapshots.\n","args":[],"type":"{ success : Basics.Bool }"},{"name":"Snapshot","comment":" Name of the snapshot and the html to be placed inside the body tag.\n`widths` specify what widths you want the html to be rendered at.\n`minimumHeight` is the minimum height in pixels of the rendered html (it will be taller if the html doesn't fit).\nIf you set `minimumHeight` to Nothing then it's always the default height of the rendered html.\n","args":["msg"],"type":"{ name : String.String, body : List.List (Html.Html msg), widths : List.Nonempty.Nonempty Basics.Int, minimumHeight : Maybe.Maybe Basics.Int }"}],"values":[{"name":"errorToString","comment":" Convert the error into a human readable form.\n","type":"Effect.Snapshot.Error -> String.String"},{"name":"uploadSnapshots","comment":" Upload snapshots to Percy.io for visual regression testing.\nYou'll need to create an account first in order to get an API key.\n\n    import Effect.Snapshot exposing (PercyApiKey(..))\n    import List.Nonempty exposing (Nonempty(..))\n    import MyLogin\n\n    heroBannerBytes =\n        ...\n\n    a =\n        uploadSnapshots\n            { apiKey = PercyApiKey \"my api token\"\n            , gitBranch = \"my-feature-branch\"\n            , gitTargetBranch = \"main\"\n            , snapshots = Nonempty { name = \"Login page\", html = MyLogin.view } []\n            , publicFiles = [ { filepath = \"hero-banner.png\", content = heroBannerBytes } ]\n            }\n\n","type":"{ apiKey : Effect.Snapshot.PercyApiKey, gitBranch : String.String, gitTargetBranch : String.String, snapshots : List.Nonempty.Nonempty (Effect.Snapshot.Snapshot msg), publicFiles : List.List Effect.Snapshot.PublicFile } -> Task.Task Effect.Snapshot.Error Effect.Snapshot.Response"}],"binops":[]},{"name":"Effect.Subscription","comment":"\n\n> **Note:** Elm has **managed effects**, meaning that things like HTTP\n> requests or writing to disk are all treated as _data_ in Elm. When this\n> data is given to the Elm runtime system, it can do some “query optimization”\n> before actually performing the effect. Perhaps unexpectedly, this managed\n> effects idea is the heart of why Elm is so nice for testing, reuse,\n> reproducibility, etc.\n>\n> Elm has two kinds of managed effects: commands and subscriptions.\n\n\n# Subscriptions\n\n@docs Subscription, none, batch, fromJs\n\n\n# Fancy Stuff\n\n@docs map\n\n","unions":[],"aliases":[{"name":"Subscription","comment":" A subscription is a way of telling Elm, “Hey, let me know if anything\ninteresting happens over there!” So if you want to listen for messages on a web\nsocket, you would tell Elm to create a subscription. If you want to get clock\nticks, you would tell Elm to subscribe to that. The cool thing here is that\nthis means _Elm_ manages all the details of subscriptions instead of _you_.\nSo if a web socket goes down, _you_ do not need to manually reconnect with an\nexponential backoff strategy, _Elm_ does this all for you behind the scenes!\n\nEvery `Sub` specifies (1) which effects you need access to and (2) the type of\nmessages that will come back into your application.\n\n**Note:** Do not worry if this seems confusing at first! As with every Elm user\never, subscriptions will make more sense as you work through [the Elm Architecture\nTutorial](https://guide.elm-lang.org/architecture/) and see how they fit\ninto a real application!\n\n","args":["restriction","msg"],"type":"Effect.Internal.Subscription restriction msg"}],"values":[{"name":"batch","comment":" When you need to subscribe to multiple things, you can create a `batch` of\nsubscriptions.\n\n**Note:** `Sub.none` and `Sub.batch [ Sub.none, Sub.none ]` and\n`Sub.batch []` all do the same thing.\n\n","type":"List.List (Effect.Subscription.Subscription restriction msg) -> Effect.Subscription.Subscription restriction msg"},{"name":"fromJs","comment":" This function listens for data from JS land. Below is an example of how to use it.\n\n    import Subscription exposing (Subscription)\n    import Command exposing (FrontendOnly)\n    import Json.Decode\n\n    port scrollEventPort : (Json.Decode.value -> msg) -> Sub msg\n\n    copyToClipboard : (Json.Decode.value -> msg) -> Subscription FrontendOnly msg\n    copyToClipboard msg =\n        Subscription.fromJs \"scrollEventPort\" scrollEventPort msg\n\n","type":"String.String -> ((Json.Decode.Value -> msg) -> Platform.Sub.Sub msg) -> (Json.Decode.Value -> msg) -> Effect.Subscription.Subscription Effect.Command.FrontendOnly msg"},{"name":"map","comment":" Transform the messages produced by a subscription.\nVery similar to [`Html.map`](/packages/elm/html/latest/Html#map).\n\nThis is very rarely useful in well-structured Elm code, so definitely read the\nsection on [structure] in the guide before reaching for this!\n\n[structure]: https://guide.elm-lang.org/webapps/structure.html\n\n","type":"(a -> b) -> Effect.Subscription.Subscription restriction a -> Effect.Subscription.Subscription restriction b"},{"name":"none","comment":" Tell the runtime that there are no subscriptions.\n","type":"Effect.Subscription.Subscription restriction msg"}],"binops":[]},{"name":"Effect.Task","comment":" Tasks make it easy to describe asynchronous operations that may fail, like\nHTTP requests or writing to a database.\n\n\n# Tasks\n\n@docs Task, perform, attempt\n\n\n# Chains\n\n@docs andThen, succeed, fail, sequence\n\n\n# Maps\n\n@docs map, map2, map3, map4, map5\n\n\n# Errors\n\n@docs onError, mapError\n\n","unions":[],"aliases":[{"name":"Task","comment":" Here are some common tasks:\n\n  - [`now : Task x Posix`][now]\n  - [`focus : String -> Task Error ()`][focus]\n  - [`sleep : Float -> Task x ()`][sleep]\n\n[now]: /packages/elm/time/latest/Time#now\n[focus]: /packages/elm/browser/latest/Browser-Dom#focus\n[sleep]: /packages/elm/core/latest/Process#sleep\n\nIn each case we have a `Task` that will resolve successfully with an `a` value\nor unsuccessfully with an `x` value. So `Browser.Dom.focus` we may fail with an\n`Error` if the given ID does not exist. Whereas `Time.now` never fails so\nI cannot be more specific than `x`. No such value will ever exist! Instead it\nalways succeeds with the current POSIX time.\n\nMore generally a task is a _description_ of what you need to do. Like a todo\nlist. Or like a grocery list. Or like GitHub issues. So saying \"the task is\nto tell me the current POSIX time\" does not complete the task! You need\n[`perform`](#perform) tasks or [`attempt`](#attempt) tasks.\n\n","args":["restriction","x","a"],"type":"Effect.Internal.Task restriction x a"}],"values":[{"name":"andThen","comment":" Chain together a task and a callback. The first task will run, and if it is\nsuccessful, you give the result to the callback resulting in another task. This\ntask then gets run. We could use this to make a task that resolves an hour from\nnow:\n\n    -- elm install elm/time\n\n\n    import Process\n    import Time\n\n    timeInOneHour : Task x Time.Posix\n    timeInOneHour =\n        Process.sleep (60 * 60 * 1000)\n            |> andThen (\\_ -> Time.now)\n\nFirst the process sleeps for an hour **and then** it tells us what time it is.\n\n","type":"(a -> Effect.Task.Task restriction x b) -> Effect.Task.Task restriction x a -> Effect.Task.Task restriction x b"},{"name":"attempt","comment":" This is very similar to [`perform`](#perform) except it can handle failures!\nSo we could _attempt_ to focus on a certain DOM node like this:\n\n    -- elm install elm/browser\n\n\n    import Browser.Dom\n    import Task\n\n    type Msg\n        = Click\n        | Search String\n        | Focus (Result Browser.DomError ())\n\n    focus : Cmd Msg\n    focus =\n        Task.attempt Focus (Browser.Dom.focus \"my-app-search-box\")\n\nSo the task is \"focus on this DOM node\" and we are turning it into the command\n\"Hey Elm, attempt to focus on this DOM node and give me a `Msg` about whether\nyou succeeded or failed.\"\n\n**Note:** Definitely work through [`guide.elm-lang.org`][guide] to get a\nfeeling for how commands fit into The Elm Architecture.\n\n[guide]: https://guide.elm-lang.org/\n\n","type":"(Result.Result x a -> msg) -> Effect.Task.Task restriction x a -> Effect.Internal.Command restriction toMsg msg"},{"name":"fail","comment":" A task that fails immediately when run. Like with `succeed`, this can be\nused with `andThen` to check on the outcome of another task.\n\n    type Error\n        = NotFound\n\n    notFound : Task Error a\n    notFound =\n        fail NotFound\n\n","type":"x -> Effect.Task.Task restriction x a"},{"name":"map","comment":" Transform a task. Maybe you want to use [`elm/time`][time] to figure\nout what time it will be in one hour:\n\n    import Task exposing (Task)\n    import Time\n\n\n    -- elm install elm/time\n    timeInOneHour : Task x Time.Posix\n    timeInOneHour =\n        Task.map addAnHour Time.now\n\n    addAnHour : Time.Posix -> Time.Posix\n    addAnHour time =\n        Time.millisToPosix (Time.posixToMillis time + 60 * 60 * 1000)\n\n[time]: /packages/elm/time/latest/\n\n","type":"(a -> b) -> Effect.Task.Task restriction x a -> Effect.Task.Task restriction x b"},{"name":"map2","comment":" Put the results of two tasks together. For example, if we wanted to know\nthe current month, we could use [`elm/time`][time] to ask:\n\n    import Task exposing (Task)\n    import Time\n\n\n    -- elm install elm/time\n    getMonth : Task x Int\n    getMonth =\n        Task.map2 Time.toMonth Time.here Time.now\n\n**Note:** Say we were doing HTTP requests instead. `map2` does each task in\norder, so it would try the first request and only continue after it succeeds.\nIf it fails, the whole thing fails!\n\n[time]: /packages/elm/time/latest/\n\n","type":"(a -> b -> result) -> Effect.Task.Task restriction x a -> Effect.Task.Task restriction x b -> Effect.Task.Task restriction x result"},{"name":"map3","comment":" ","type":"(a -> b -> c -> result) -> Effect.Task.Task restriction x a -> Effect.Task.Task restriction x b -> Effect.Task.Task restriction x c -> Effect.Task.Task restriction x result"},{"name":"map4","comment":" ","type":"(a -> b -> c -> d -> result) -> Effect.Task.Task restriction x a -> Effect.Task.Task restriction x b -> Effect.Task.Task restriction x c -> Effect.Task.Task restriction x d -> Effect.Task.Task restriction x result"},{"name":"map5","comment":" ","type":"(a -> b -> c -> d -> e -> result) -> Effect.Task.Task restriction x a -> Effect.Task.Task restriction x b -> Effect.Task.Task restriction x c -> Effect.Task.Task restriction x d -> Effect.Task.Task restriction x e -> Effect.Task.Task restriction x result"},{"name":"mapError","comment":" Transform the error value. This can be useful if you need a bunch of error\ntypes to match up.\n\n    type Error\n        = Http Http.Error\n        | WebGL WebGL.Error\n\n    getResources : Task Error Resource\n    getResources =\n        sequence\n            [ mapError Http serverTask\n            , mapError WebGL textureTask\n            ]\n\n","type":"(x -> y) -> Effect.Task.Task restriction x a -> Effect.Task.Task restriction y a"},{"name":"onError","comment":" Recover from a failure in a task. If the given task fails, we use the\ncallback to recover.\n\n    fail \"file not found\"\n      |> onError (\\msg -> succeed 42)\n      -- succeed 42\n\n    succeed 9\n      |> onError (\\msg -> succeed 42)\n      -- succeed 9\n\n","type":"(x -> Effect.Task.Task restriction y a) -> Effect.Task.Task restriction x a -> Effect.Task.Task restriction y a"},{"name":"perform","comment":" Like I was saying in the [`Task`](#Task) documentation, just having a\n`Task` does not mean it is done. We must command Elm to `perform` the task:\n\n    -- elm install elm/time\n\n\n    import Task\n    import Time\n\n    type Msg\n        = Click\n        | Search String\n        | NewTime Time.Posix\n\n    getNewTime : Cmd Msg\n    getNewTime =\n        Task.perform NewTime Time.now\n\nIf you have worked through [`guide.elm-lang.org`][guide] (highly recommended!)\nyou will recognize `Cmd` from the section on The Elm Architecture. So we have\nchanged a task like \"make delicious lasagna\" into a command like \"Hey Elm, make\ndelicious lasagna and give it to my `update` function as a `Msg` value.\"\n\n[guide]: https://guide.elm-lang.org/\n\n","type":"(a -> msg) -> Effect.Task.Task restriction Basics.Never a -> Effect.Internal.Command restriction toMsg msg"},{"name":"sequence","comment":" Start with a list of tasks, and turn them into a single task that returns a\nlist. The tasks will be run in order one-by-one and if any task fails the whole\nsequence fails.\n\n    sequence [ succeed 1, succeed 2 ] == succeed [ 1, 2 ]\n\n","type":"List.List (Effect.Task.Task restriction x a) -> Effect.Task.Task restriction x (List.List a)"},{"name":"succeed","comment":" A task that succeeds immediately when run. It is usually used with\n[`andThen`](#andThen). You can use it like `map` if you want:\n\n    import Time\n\n\n    -- elm install elm/time\n    timeInMillis : Task x Int\n    timeInMillis =\n        Time.now\n            |> andThen (\\t -> succeed (Time.posixToMillis t))\n\n","type":"a -> Effect.Task.Task restriction x a"}],"binops":[]},{"name":"Effect.Test","comment":"\n\n\n## Setting up end to end tests\n\n@docs start, Config, connectFrontend, FrontendApp, BackendApp, HttpRequest, HttpResponse, RequestedBy, PortToJs, FileData, FileUpload, MultipleFilesUpload, uploadBytesFile, uploadStringFile, Data, FileContents\n\n\n## Control the tests\n\n@docs FrontendActions, backendUpdate, fastForward, group, andThen, EndToEndTest, Action, HttpBody, HttpPart, DelayInMs, KeyEvent, KeyOptions, PointerEvent, PointerOptions\n\n\n## Check the current state\n\n@docs checkState, checkBackend, toTest, toSnapshots\n\n\n## Test viewer\n\nSometimes it's hard to tell what's going on in an end to end test. One way to make this easier to use the `viewer` function. It's like a test runner for your browser that also lets you see the frontend of an app as simulated inputs are being triggered.\n\n@docs fakeNavigationKey, viewer, Msg, Model, viewerWith, ViewerWith, startViewer, addStringFile, addStringFiles, addBytesFile, addBytesFiles, addTexture, addTextureWithOptions\n\n\n## Test runner\n\nIf you want to just run the end to end tests to make sure they work, or automatically check that they pass in your CI pipeline then you can setup a headless test runner with this function:\n\n@docs startHeadless, HeadlessMsg\n\n\n## Types\n\n@docs Button, WheelOptions, DeltaMode, CurrentTimeline, EventFrontend, EventType, FileLoadError, FileLoadErrorType, MouseEvent, OverlayPosition, TestError, Touch, TouchEvent\n\n\n## Setting up end-to-end tests for non-Lamdera apps\n\n@docs configForApplication, configForDocument, configForElement, configForSandbox\n\n","unions":[{"name":"Action","comment":" ","args":["toBackend","frontendMsg","frontendModel","toFrontend","backendMsg","backendModel"],"cases":[]},{"name":"Button","comment":" ","args":[],"cases":[["MainButton",[]],["MiddleButton",[]],["SecondButton",[]],["BackButton",[]],["ForwardButton",[]]]},{"name":"CurrentTimeline","comment":" ","args":[],"cases":[]},{"name":"DeltaMode","comment":" <https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaMode>. The default is DeltaPixels so it's not included here\n","args":[],"cases":[["DeltaLines",[]],["DeltaPages",[]]]},{"name":"EndToEndTest","comment":" ","args":["toBackend","frontendMsg","frontendModel","toFrontend","backendMsg","backendModel"],"cases":[]},{"name":"EventType","comment":" ","args":["toBackend","frontendMsg","frontendModel","toFrontend","backendMsg","backendModel"],"cases":[]},{"name":"FileContents","comment":" ","args":[],"cases":[["StringFile",["String.String"]],["BytesFile",["Bytes.Bytes"]]]},{"name":"FileData","comment":" File data for when simulating a user uploading a file via `Effect.File.Select.file` or `Effect.File.Select.files`\n","args":[],"cases":[]},{"name":"FileLoadErrorType","comment":" ","args":[],"cases":[]},{"name":"FileUpload","comment":" Possible simulated user actions for when `Effect.File.Select.file` is triggered.\n","args":[],"cases":[["UploadFile",["Effect.Test.FileData"]],["UnhandledFileUpload",[]]]},{"name":"HeadlessMsg","comment":" Msg type for a headless end to end test runner.\n","args":["toBackend","frontendMsg","frontendModel","toFrontend","backendMsg","backendModel"],"cases":[]},{"name":"HttpBody","comment":" ","args":[],"cases":[["EmptyBody",[]],["StringBody",["{ contentType : String.String, content : String.String }"]],["JsonBody",["Json.Encode.Value"]],["MultipartBody",["List.List Effect.Test.HttpPart"]],["BytesBody",["String.String","Bytes.Bytes"]],["FileBody",["Effect.Internal.File"]]]},{"name":"HttpPart","comment":" ","args":[],"cases":[["StringPart",["String.String","String.String"]],["FilePart",["String.String","Effect.Internal.File"]],["BytesPart",["{ key : String.String, mimeType : String.String, content : Bytes.Bytes }"]]]},{"name":"HttpResponse","comment":" The response for an http request.\nNote that if the http request was expecting one form of data (for example json) and the response contains a different type of data (for example a String) then the data will automatically be converted.\nThe exception to this is Texture. If the request is expecting a Texture (this will only happen with `Effect.WebGL.Texture.load` and `Effect.WebGL.Texture.loadWith`) then the response has to contain a Texture if you want the request to succeed.\nIn other words, sending the Bytes that represent that texture won't work.\n","args":[],"cases":[["BadUrlResponse",["String.String"]],["TimeoutResponse",[]],["NetworkErrorResponse",[]],["BadStatusResponse",["Effect.Http.Metadata","String.String"]],["BytesHttpResponse",["Effect.Http.Metadata","Bytes.Bytes"]],["StringHttpResponse",["Effect.Http.Metadata","String.String"]],["JsonHttpResponse",["Effect.Http.Metadata","Json.Encode.Value"]],["TextureHttpResponse",["Effect.Http.Metadata","Effect.WebGL.Texture.Texture"]],["UnhandledHttpRequest",[]]]},{"name":"KeyOptions","comment":" ","args":[],"cases":[["Key_ShiftHeld",[]],["Key_CtrlHeld",[]],["Key_MetaHeld",[]],["Key_AltHeld",[]]]},{"name":"Model","comment":" ","args":["toBackend","frontendMsg","frontendModel","toFrontend","backendMsg","backendModel"],"cases":[]},{"name":"Msg","comment":" ","args":["toBackend","frontendMsg","frontendModel","toFrontend","backendMsg","backendModel"],"cases":[]},{"name":"MultipleFilesUpload","comment":" Possible simulated user actions for when `Effect.File.Select.files` is triggered.\n","args":[],"cases":[["UploadMultipleFiles",["Effect.Test.FileData","List.List Effect.Test.FileData"]],["UnhandledMultiFileUpload",[]]]},{"name":"OverlayPosition","comment":" ","args":[],"cases":[]},{"name":"PointerOptions","comment":" ","args":[],"cases":[["PointerId",["Basics.Int"]],["ScreenXY",["Basics.Float","Basics.Float"]],["PageXY",["Basics.Float","Basics.Float"]],["ClientXY",["Basics.Float","Basics.Float"]],["ShiftHeld",[]],["CtrlHeld",[]],["MetaHeld",[]],["AltHeld",[]],["PointerType",["String.String"]],["IsNotPrimary",[]],["PointerWidth",["Basics.Float"]],["PointerHeight",["Basics.Float"]],["PointerPressure",["Basics.Float"]],["PointerTilt",["Basics.Float","Basics.Float"]],["PointerButton",["Effect.Test.Button"]]]},{"name":"RequestedBy","comment":" Who made this http request?\n","args":[],"cases":[["RequestedByFrontend",["Effect.Lamdera.ClientId"]],["RequestedByBackend",[]]]},{"name":"TestError","comment":" ","args":[],"cases":[]},{"name":"WheelOptions","comment":" <https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event>\n","args":[],"cases":[["DeltaX",["Basics.Float"]],["DeltaZ",["Basics.Float"]],["DeltaMode",["Effect.Test.DeltaMode"]]]}],"aliases":[{"name":"BackendApp","comment":" ","args":["toBackend","toFrontend","backendMsg","backendModel"],"type":"{ init : ( backendModel, Effect.Internal.Command Effect.Command.BackendOnly toFrontend backendMsg ), update : backendMsg -> backendModel -> ( backendModel, Effect.Internal.Command Effect.Command.BackendOnly toFrontend backendMsg ), updateFromFrontend : Effect.Lamdera.SessionId -> Effect.Lamdera.ClientId -> toBackend -> backendModel -> ( backendModel, Effect.Internal.Command Effect.Command.BackendOnly toFrontend backendMsg ), subscriptions : backendModel -> Effect.Subscription.Subscription Effect.Command.BackendOnly backendMsg }"},{"name":"Config","comment":" Configure the end to end test before starting it\n\n    import Backend\n    import Effect.Test\n    import Frontend\n    import Test exposing (Test)\n    import Url\n\n    config =\n        { frontendApp = Frontend.appFunctions\n        , backendApp = Backend.appFunctions\n        , handleHttpRequest = always Effect.Test.UnhandledHttpRequest\n        , handlePortToJs = always Nothing\n        , handleFileUpload = always Effect.Test.UnhandledFileUpload\n        , handleMultipleFilesUpload = always Effect.Test.UnhandledMultiFileUpload\n        , domain = unsafeUrl \"https://my-app.lamdera.app\"\n        }\n\n    test : Test\n    test =\n        Effect.Test.start \"myButton is clickable\"\n            |> Effect.Test.connectFrontend\n                sessionId0\n                myDomain\n                { width = 1920, height = 1080 }\n                (\\( state, frontendActions ) ->\n                    state\n                        |> frontendActions.click { htmlId = \"myButton\" }\n                )\n            |> Effect.Test.toTest\n\n    unsafeUrl : String -> Url\n    unsafeUrl urlText =\n        case Url.fromString urlText of\n            Just url ->\n                url\n\n            Nothing ->\n                unsafeUrl urlText\n\n","args":["toBackend","frontendMsg","frontendModel","toFrontend","backendMsg","backendModel"],"type":"{ frontendApp : Effect.Test.FrontendApp toBackend frontendMsg frontendModel toFrontend, backendApp : Effect.Test.BackendApp toBackend toFrontend backendMsg backendModel, handleHttpRequest : { data : Effect.Test.Data frontendModel backendModel, currentRequest : Effect.Test.HttpRequest } -> Effect.Test.HttpResponse, handlePortToJs : { data : Effect.Test.Data frontendModel backendModel, currentRequest : Effect.Test.PortToJs } -> Maybe.Maybe ( String.String, Json.Decode.Value ), handleFileUpload : { data : Effect.Test.Data frontendModel backendModel, mimeTypes : List.List String.String } -> Effect.Test.FileUpload, handleMultipleFilesUpload : { data : Effect.Test.Data frontendModel backendModel, mimeTypes : List.List String.String } -> Effect.Test.MultipleFilesUpload, domain : Url.Url }"},{"name":"Data","comment":" ","args":["frontendModel","backendModel"],"type":"{ httpRequests : List.List Effect.Test.HttpRequest, portRequests : List.List Effect.Test.PortToJs, fileUploads : List.List { uploadedAt : Time.Posix, uploadedBy : Effect.Lamdera.ClientId, upload : Effect.Test.FileUpload }, multipleFileUploads : List.List { uploadedAt : Time.Posix, uploadedBy : Effect.Lamdera.ClientId, upload : Effect.Test.MultipleFilesUpload }, time : Time.Posix, backend : backendModel, frontends : SeqDict.SeqDict Effect.Lamdera.ClientId frontendModel, downloads : List.List { filename : String.String, mimeType : String.String, content : Effect.Test.FileContents, downloadedAt : Time.Posix } }"},{"name":"DelayInMs","comment":" How many milliseconds to delay something by\n","args":[],"type":"Basics.Float"},{"name":"EventFrontend","comment":" ","args":["frontendModel"],"type":"{ model : frontendModel, sessionId : Effect.Lamdera.SessionId, url : Url.Url, windowSize : { width : Basics.Int, height : Basics.Int } }"},{"name":"FileLoadError","comment":" ","args":[],"type":"{ name : String.String, error : Effect.Test.FileLoadErrorType }"},{"name":"FrontendActions","comment":" FrontendActions contains the possible functions we can call on the client we just connected.\n\n    import Effect.Test\n    import Test exposing (Test)\n    import Url\n\n    config =\n        { frontendApp = Frontend.appFunctions\n        , backendApp = Backend.appFunctions\n        , handleHttpRequest = always Effect.Test.UnhandledHttpRequest\n        , handlePortToJs = always Nothing\n        , handleFileUpload = always Effect.Test.UnhandledFileUpload\n        , handleMultipleFilesUpload = always Effect.Test.UnhandledMultiFileUpload\n        , domain = unsafeUrl \"https://my-app.lamdera.app\"\n        }\n\n    test : Test\n    test =\n        Effect.Test.start \"myButton is clickable\"\n            |> Effect.Test.connectFrontend\n                sessionId0\n                myDomain\n                { width = 1920, height = 1080 }\n                (\\( state, frontendActions ) ->\n                    -- frontendActions is a record we can use on this specific frontend we just connected\n                    state\n                        |> frontendActions.click { htmlId = \"myButton\" }\n                )\n            |> Effect.Test.toTest\n\n    unsafeUrl : String -> Url\n    unsafeUrl urlText =\n        case Url.fromString urlText of\n            Just url ->\n                url\n\n            Nothing ->\n                unsafeUrl urlText\n\n","args":["toBackend","frontendMsg","frontendModel","toFrontend","backendMsg","backendModel"],"type":"{ clientId : Effect.Lamdera.ClientId, keyDown : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.KeyEvent -> List.List Effect.Test.KeyOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, keyUp : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.KeyEvent -> List.List Effect.Test.KeyOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, pointerDown : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.PointerEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, pointerUp : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.PointerEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, pointerEnter : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.PointerEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, pointerOut : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.PointerEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, pointerCancel : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.PointerEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, pointerMove : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.PointerEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, pointerLeave : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.PointerEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, pointerOver : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.PointerEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, touchStart : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.TouchEvent -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, touchMove : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.TouchEvent -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, touchEnd : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.TouchEvent -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, touchCancel : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.TouchEvent -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, mouseDown : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.MouseEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, mouseUp : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.MouseEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, mouseEnter : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.MouseEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, mouseOut : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.MouseEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, mouseMove : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.MouseEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, mouseLeave : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.MouseEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, mouseOver : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.MouseEvent -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, wheel : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Basics.Float -> ( Basics.Float, Basics.Float ) -> List.List Effect.Test.WheelOptions -> List.List Effect.Test.PointerOptions -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, focus : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, blur : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, click : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, input : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> String.String -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, clickLink : Effect.Test.DelayInMs -> String.String -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, resizeWindow : Effect.Test.DelayInMs -> { width : Basics.Int, height : Basics.Int } -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, checkView : Effect.Test.DelayInMs -> (Test.Html.Query.Single frontendMsg -> Expect.Expectation) -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, update : Effect.Test.DelayInMs -> frontendMsg -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, sendToBackend : Effect.Test.DelayInMs -> toBackend -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, snapshotView : Effect.Test.DelayInMs -> { name : String.String } -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, checkModel : Effect.Test.DelayInMs -> (frontendModel -> Result.Result String.String ()) -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, custom : Effect.Test.DelayInMs -> Effect.Browser.Dom.HtmlId -> String.String -> Json.Encode.Value -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, portEvent : Effect.Test.DelayInMs -> String.String -> Json.Encode.Value -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, navigateBack : Effect.Test.DelayInMs -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel, navigateForward : Effect.Test.DelayInMs -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel }"},{"name":"FrontendApp","comment":" ","args":["toBackend","frontendMsg","frontendModel","toFrontend"],"type":"{ init : Url.Url -> Effect.Browser.Navigation.Key -> ( frontendModel, Effect.Internal.Command Effect.Command.FrontendOnly toBackend frontendMsg ), onUrlRequest : Browser.UrlRequest -> frontendMsg, onUrlChange : Url.Url -> frontendMsg, update : frontendMsg -> frontendModel -> ( frontendModel, Effect.Internal.Command Effect.Command.FrontendOnly toBackend frontendMsg ), updateFromBackend : toFrontend -> frontendModel -> ( frontendModel, Effect.Internal.Command Effect.Command.FrontendOnly toBackend frontendMsg ), view : frontendModel -> Browser.Document frontendMsg, subscriptions : frontendModel -> Effect.Subscription.Subscription Effect.Command.FrontendOnly frontendMsg }"},{"name":"HttpRequest","comment":" ","args":[],"type":"{ requestedBy : Effect.Test.RequestedBy, method : String.String, url : String.String, body : Effect.Test.HttpBody, headers : List.List ( String.String, String.String ), sentAt : Time.Posix }"},{"name":"KeyEvent","comment":" ","args":[],"type":"String.String"},{"name":"MouseEvent","comment":" ","args":[],"type":"( Basics.Float, Basics.Float )"},{"name":"PointerEvent","comment":" ","args":[],"type":"( Basics.Float, Basics.Float )"},{"name":"PortToJs","comment":" ","args":[],"type":"{ clientId : Effect.Lamdera.ClientId, portName : String.String, value : Json.Encode.Value }"},{"name":"Touch","comment":" ","args":[],"type":"{ id : Basics.Int, clientPos : ( Basics.Float, Basics.Float ), pagePos : ( Basics.Float, Basics.Float ), screenPos : ( Basics.Float, Basics.Float ) }"},{"name":"TouchEvent","comment":" ","args":[],"type":"{ changedTouches : List.List Effect.Test.Touch, targetTouches : List.List Effect.Test.Touch }"},{"name":"ViewerWith","comment":" ","args":["a"],"type":"{ cmds : Task.Task Effect.Test.FileLoadError a }"}],"values":[{"name":"addBytesFile","comment":" Add a file containing binary data to your tests.\n\n    import Effect.Test\n\n    main =\n        Effect.Test.viewerWith\n            (\\image jsonData ->\n                [{- End to end tests go here -}]\n            )\n            |> Effect.Test.addBytesFile \"/test.png\"\n            |> Effect.Test.addBytesFile \"/data.json\"\n            |> Effect.Test.startViewer\n\n","type":"String.String -> Effect.Test.ViewerWith (Bytes.Bytes -> b) -> Effect.Test.ViewerWith b"},{"name":"addBytesFiles","comment":" Add multiple files containing binary data to your tests.\n\n    import Effect.Test\n\n    main =\n        Effect.Test.viewerWith\n            (\\dict ->\n                [{- End to end tests go here -}]\n            )\n            |> Effect.Test.addBytesFiles [ \"/test.png\", \"/data.json\" ]\n            |> Effect.Test.startViewer\n\n","type":"List.List String.String -> Effect.Test.ViewerWith (Dict.Dict String.String Bytes.Bytes -> b) -> Effect.Test.ViewerWith b"},{"name":"addStringFile","comment":" Add a file containing text data to your tests.\n\n    import Effect.Test\n\n    main =\n        Effect.Test.viewerWith\n            (\\text jsonData ->\n                [{- End to end tests go here -}]\n            )\n            |> Effect.Test.addStringFile \"/test.txt\"\n            |> Effect.Test.addStringFile \"/data.json\"\n            |> Effect.Test.startViewer\n\n","type":"String.String -> Effect.Test.ViewerWith (String.String -> b) -> Effect.Test.ViewerWith b"},{"name":"addStringFiles","comment":" Add multiple files containing text data to your tests.\n\n    import Effect.Test\n\n    main =\n        Effect.Test.viewerWith\n            (\\dict ->\n                [{- End to end tests go here -}]\n            )\n            |> Effect.Test.addStringFiles [ \"/test.txt\", \"/data.json\" ]\n            |> Effect.Test.startViewer\n\n","type":"List.List String.String -> Effect.Test.ViewerWith (Dict.Dict String.String String.String -> b) -> Effect.Test.ViewerWith b"},{"name":"addTexture","comment":" Add a file containing data for a `Effect.WebGL.Texture.Texture` to your tests. Right now this is performed with HTTP get requests which means you can only access files in /public (or make get requests to other websites though this isn't recommended since this API might change in the future)\n\n    import Effect.Test\n\n    main =\n        Effect.Test.viewerWith\n            (\\texture ->\n                [{- End to end tests go here -}]\n            )\n            |> Effect.Test.addTextureFile \"/texture.png\"\n            |> Effect.Test.startViewer\n\n","type":"String.String -> Effect.Test.ViewerWith (Effect.WebGL.Texture.Texture -> b) -> Effect.Test.ViewerWith b"},{"name":"addTextureWithOptions","comment":" Add a file containing data for a `Effect.WebGL.Texture.Texture` to your tests. Right now this is performed with HTTP get requests which means you can only access files in /public (or make get requests to other websites though this isn't recommended since this API might change in the future)\n\n    import Effect.Test\n\n    main =\n        Effect.Test.viewerWith\n            (\\texture ->\n                [{- End to end tests go here -}]\n            )\n            |> Effect.Test.addTextureFileWithOptions\n                -- WebGL texture options go here\n                \"/texture.png\"\n            |> Effect.Test.startViewer\n\n","type":"Effect.WebGL.Texture.Options -> String.String -> Effect.Test.ViewerWith (Effect.WebGL.Texture.Texture -> b) -> Effect.Test.ViewerWith b"},{"name":"andThen","comment":" Sometimes you need to decide what should happen next based on some current state.\nTo do that you can write something like this:\n\n    import Effect.Test\n\n    Effect.Test.andThen\n        100 -- Simulate 100 milliseconds before performing this action\n        (\\data ->\n            case List.filterMap isLoginEmail data.httpRequests |> List.head of\n                Just loginEmail ->\n                    [ Effect.Test.connectFrontend\n                        100\n                        sessionIdFromEmail\n                        \"/user-overview\"\n                        (\\clientIdFromEmail ->\n                            [ ... ]\n                        )\n                    ]\n\n                Nothing ->\n                    [ Effect.Test.checkState (\\_ -> Err \"Should have gotten a login email\") ]\n        )\n\n","type":"Effect.Test.DelayInMs -> (Effect.Test.Data frontendModel backendModel -> List.List (Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel)) -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel"},{"name":"backendUpdate","comment":" Directly trigger an update on the backend. Normally you shouldn't need to do this as things like Time.every and completed tasks will generate updates automatically.\n","type":"Effect.Test.DelayInMs -> backendMsg -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel"},{"name":"checkBackend","comment":" Make the test fail if the backend model doesn't seem some condition.\n","type":"Effect.Test.DelayInMs -> (backendModel -> Result.Result String.String ()) -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel"},{"name":"checkState","comment":" Make the test fail if it doesn't seem some condition.\n","type":"Effect.Test.DelayInMs -> (Effect.Test.Data frontendModel backendModel -> Result.Result String.String ()) -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel"},{"name":"configForApplication","comment":" Test config for a Browser.application app. See the examples folder for how to setup end-to-end tests for your app.\n","type":"{ flags : flags, frontendApp : { init : flags -> Url.Url -> Effect.Browser.Navigation.Key -> ( frontendModel, Effect.Internal.Command Effect.Command.FrontendOnly Basics.Never frontendMsg ), view : frontendModel -> Browser.Document frontendMsg, update : frontendMsg -> frontendModel -> ( frontendModel, Effect.Internal.Command Effect.Command.FrontendOnly Basics.Never frontendMsg ), subscriptions : frontendModel -> Effect.Subscription.Subscription Effect.Command.FrontendOnly frontendMsg, onUrlRequest : Browser.UrlRequest -> frontendMsg, onUrlChange : Url.Url -> frontendMsg }, handleHttpRequest : { data : Effect.Test.Data frontendModel (), currentRequest : Effect.Test.HttpRequest } -> Effect.Test.HttpResponse, handlePortToJs : { data : Effect.Test.Data frontendModel (), currentRequest : Effect.Test.PortToJs } -> Maybe.Maybe ( String.String, Json.Decode.Value ), handleFileUpload : { data : Effect.Test.Data frontendModel (), mimeTypes : List.List String.String } -> Effect.Test.FileUpload, handleMultipleFilesUpload : { data : Effect.Test.Data frontendModel (), mimeTypes : List.List String.String } -> Effect.Test.MultipleFilesUpload, domain : Url.Url } -> Effect.Test.Config Basics.Never frontendMsg frontendModel Basics.Never Basics.Never ()"},{"name":"configForDocument","comment":" Test config for a Browser.document app. See the examples folder for how to setup end-to-end tests for your app.\n","type":"{ flags : flags, noOpMsg : frontendMsg, frontendApp : { init : flags -> ( frontendModel, Effect.Internal.Command Effect.Command.FrontendOnly Basics.Never frontendMsg ), view : frontendModel -> Browser.Document frontendMsg, update : frontendMsg -> frontendModel -> ( frontendModel, Effect.Internal.Command Effect.Command.FrontendOnly Basics.Never frontendMsg ), subscriptions : frontendModel -> Effect.Subscription.Subscription Effect.Command.FrontendOnly frontendMsg }, handleHttpRequest : { data : Effect.Test.Data frontendModel (), currentRequest : Effect.Test.HttpRequest } -> Effect.Test.HttpResponse, handlePortToJs : { data : Effect.Test.Data frontendModel (), currentRequest : Effect.Test.PortToJs } -> Maybe.Maybe ( String.String, Json.Decode.Value ), handleFileUpload : { data : Effect.Test.Data frontendModel (), mimeTypes : List.List String.String } -> Effect.Test.FileUpload, handleMultipleFilesUpload : { data : Effect.Test.Data frontendModel (), mimeTypes : List.List String.String } -> Effect.Test.MultipleFilesUpload, domain : Url.Url } -> Effect.Test.Config Basics.Never frontendMsg frontendModel Basics.Never Basics.Never ()"},{"name":"configForElement","comment":" Test config for a Browser.element app. See the examples folder for how to setup end-to-end tests for your app.\n","type":"{ flags : flags, noOpMsg : frontendMsg, frontendApp : { init : flags -> ( frontendModel, Effect.Internal.Command Effect.Command.FrontendOnly Basics.Never frontendMsg ), view : frontendModel -> Html.Html frontendMsg, update : frontendMsg -> frontendModel -> ( frontendModel, Effect.Internal.Command Effect.Command.FrontendOnly Basics.Never frontendMsg ), subscriptions : frontendModel -> Effect.Subscription.Subscription Effect.Command.FrontendOnly frontendMsg }, handleHttpRequest : { data : Effect.Test.Data frontendModel (), currentRequest : Effect.Test.HttpRequest } -> Effect.Test.HttpResponse, handlePortToJs : { data : Effect.Test.Data frontendModel (), currentRequest : Effect.Test.PortToJs } -> Maybe.Maybe ( String.String, Json.Decode.Value ), handleFileUpload : { data : Effect.Test.Data frontendModel (), mimeTypes : List.List String.String } -> Effect.Test.FileUpload, handleMultipleFilesUpload : { data : Effect.Test.Data frontendModel (), mimeTypes : List.List String.String } -> Effect.Test.MultipleFilesUpload, domain : Url.Url } -> Effect.Test.Config Basics.Never frontendMsg frontendModel Basics.Never Basics.Never ()"},{"name":"configForSandbox","comment":" Test config for a Browser.sandbox app. See the examples folder for how to setup end-to-end tests for your app.\n","type":"{ noOpMsg : frontendMsg, frontendApp : { init : frontendModel, view : frontendModel -> Html.Html frontendMsg, update : frontendMsg -> frontendModel -> frontendModel }, handleHttpRequest : { data : Effect.Test.Data frontendModel (), currentRequest : Effect.Test.HttpRequest } -> Effect.Test.HttpResponse, handlePortToJs : { data : Effect.Test.Data frontendModel (), currentRequest : Effect.Test.PortToJs } -> Maybe.Maybe ( String.String, Json.Decode.Value ), handleFileUpload : { data : Effect.Test.Data frontendModel (), mimeTypes : List.List String.String } -> Effect.Test.FileUpload, handleMultipleFilesUpload : { data : Effect.Test.Data frontendModel (), mimeTypes : List.List String.String } -> Effect.Test.MultipleFilesUpload, domain : Url.Url } -> Effect.Test.Config Basics.Never frontendMsg frontendModel Basics.Never Basics.Never ()"},{"name":"connectFrontend","comment":" Add a frontend client to the end to end test\n\n    import Effect.Test\n    import Test exposing (Test)\n    import Url\n\n    testApp =\n        Effect.Test.testApp\n            Frontend.appFunctions\n            Backend.appFunctions\n            (always NetworkError_)\n            (always Nothing)\n            (always Nothing)\n            (unsafeUrl \"https://my-app.lamdera.app\")\n\n    test : Test\n    test =\n        testApp \"myButton is clickable\"\n            |> Effect.Test.connectFrontend\n                sessionId0\n                \"/\"\n                { width = 1920, height = 1080 }\n                (\\( state, frontendActions ) ->\n                    state\n                        |> frontendActions.click { htmlId = \"myButton\" }\n                )\n            |> Effect.Test.toTest\n\n    unsafeUrl : String -> Url\n    unsafeUrl urlText =\n        case Url.fromString urlText of\n            Just url ->\n                url\n\n            Nothing ->\n                unsafeUrl urlText\n\n","type":"Effect.Test.DelayInMs -> Effect.Lamdera.SessionId -> String.String -> { width : Basics.Int, height : Basics.Int } -> (Effect.Test.FrontendActions toBackend frontendMsg frontendModel toFrontend backendMsg backendModel -> List.List (Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel)) -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel"},{"name":"fakeNavigationKey","comment":" Only use this for tests!\n","type":"Effect.Browser.Navigation.Key"},{"name":"fastForward","comment":" Similar to `wait` but this will not trigger any `Browser.onAnimationFrame` or `Time.every` subscriptions.\n\nThis is useful if you need to move the clock forward a week and it would take too long to simulate it perfectly.\n\n","type":"Duration.Duration -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel"},{"name":"group","comment":" ","type":"List.List (Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel) -> Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel"},{"name":"start","comment":" Start a end-to-end test\n\n    import Backend\n    import Effect.Test\n    import Frontend\n    import Test exposing (Test)\n    import Url\n\n    config =\n        { frontendApp = Frontend.appFunctions\n        , backendApp = Backend.appFunctions\n        , handleHttpRequest = always Effect.Test.NetworkErrorResponse\n        , handlePortToJs = always Nothing\n        , handleFileUpload = always Effect.Test.UnhandledFileUpload\n        , handleMultipleFilesUpload = always Effect.Test.UnhandledMultiFileUpload\n        , domain = unsafeUrl \"https://my-app.lamdera.app\"\n        }\n\n    test : Test\n    test =\n        Effect.Test.start \"myButton is clickable\"\n            |> Effect.Test.connectFrontend\n                sessionId0\n                myDomain\n                { width = 1920, height = 1080 }\n                (\\( state, frontendActions ) ->\n                    state\n                        |> frontendActions.click { htmlId = \"myButton\" }\n                )\n            |> Effect.Test.toTest\n\n    unsafeUrl : String -> Url\n    unsafeUrl urlText =\n        case Url.fromString urlText of\n            Just url ->\n                url\n\n            Nothing ->\n                unsafeUrl urlText\n\n","type":"String.String -> Time.Posix -> Effect.Test.Config toBackend frontendMsg frontendModel toFrontend backendMsg backendModel -> List.List (Effect.Test.Action toBackend frontendMsg frontendModel toFrontend backendMsg backendModel) -> Effect.Test.EndToEndTest toBackend frontendMsg frontendModel toFrontend backendMsg backendModel"},{"name":"startHeadless","comment":" Create a headless test runner.\n\n    import Effect.Test\n\n    main =\n        Effect.Test.viewerWith\n            (\\image jsonData ->\n                [{- End to end tests go here -}]\n            )\n            |> Effect.Test.addBytesFile \"/test.png\"\n            |> Effect.Test.addBytesFile \"/data.json\"\n            |> Effect.Test.startHeadless\n\n","type":"(Json.Encode.Value -> Platform.Cmd.Cmd (Effect.Test.HeadlessMsg toBackend frontendMsg frontendModel toFrontend backendMsg backendModel)) -> Effect.Test.ViewerWith (List.List (Effect.Test.EndToEndTest toBackend frontendMsg frontendModel toFrontend backendMsg backendModel)) -> Platform.Program () () (Effect.Test.HeadlessMsg toBackend frontendMsg frontendModel toFrontend backendMsg backendModel)"},{"name":"startViewer","comment":" View your end-to-end tests in a elm reactor style app.\n\n    import Effect.Test\n\n    main =\n        Effect.Test.viewerWith\n            (\\image jsonData ->\n                [{- End to end tests go here -}]\n            )\n            |> Effect.Test.addBytesFile \"/test.png\"\n            |> Effect.Test.addBytesFile \"/data.json\"\n            |> Effect.Test.startViewer\n\n","type":"Effect.Test.ViewerWith (List.List (Effect.Test.EndToEndTest toBackend frontendMsg frontendModel toFrontend backendMsg backendModel)) -> Platform.Program () (Effect.Test.Model toBackend frontendMsg frontendModel toFrontend backendMsg backendModel) (Effect.Test.Msg toBackend frontendMsg frontendModel toFrontend backendMsg backendModel)"},{"name":"toSnapshots","comment":" Get all snapshots from a test.\nThis can be used with Effect.Snapshot.uploadSnapshots to perform visual regression testing.\n","type":"Effect.Test.EndToEndTest toBackend frontendMsg frontendModel toFrontend backendMsg backendModel -> List.List (Effect.Snapshot.Snapshot frontendMsg)"},{"name":"toTest","comment":" ","type":"Effect.Test.EndToEndTest toBackend frontendMsg frontendModel toFrontend backendMsg backendModel -> Test.Test"},{"name":"uploadBytesFile","comment":" Create a file upload containing binary data\n","type":"String.String -> String.String -> Bytes.Bytes -> Time.Posix -> Effect.Test.FileData"},{"name":"uploadStringFile","comment":" Create a file upload containing text data\n","type":"String.String -> String.String -> String.String -> Time.Posix -> Effect.Test.FileData"},{"name":"viewer","comment":" View your end-to-end tests in a elm reactor style app.\n\n        main =\n            viewer [{- End to end tests go here -}]\n\n","type":"List.List (Effect.Test.EndToEndTest toBackend frontendMsg frontendModel toFrontend backendMsg backendModel) -> Platform.Program () (Effect.Test.Model toBackend frontendMsg frontendModel toFrontend backendMsg backendModel) (Effect.Test.Msg toBackend frontendMsg frontendModel toFrontend backendMsg backendModel)"},{"name":"viewerWith","comment":" View your end-to-end tests in a elm reactor style app.\n\n    import Effect.Test\n\n    main =\n        Effect.Test.viewerWith\n            (\\image jsonData ->\n                [{- End to end tests go here -}]\n            )\n            |> Effect.Test.addBytesFile \"/test.png\"\n            |> Effect.Test.addBytesFile \"/data.json\"\n            |> Effect.Test.startViewer\n\n","type":"a -> Effect.Test.ViewerWith a"}],"binops":[]},{"name":"Effect.Time","comment":" Library for working with time and time zones.\n\n\n# Time\n\n@docs Posix, now, every, posixToMillis, millisToPosix\n\n\n# Time Zones\n\n@docs Zone, utc, here\n\n\n# Human Times\n\n@docs toYear, toMonth, toDay, toWeekday, toHour, toMinute, toSecond, toMillis\n\n\n# Weeks and Months\n\n@docs Weekday, Month\n\n\n# For Package Authors\n\n@docs customZone, getZoneName, ZoneName\n\n","unions":[{"name":"ZoneName","comment":" **Intended for package authors.**\n\nThe `getZoneName` function relies on a JavaScript API that is not supported\nin all browsers yet, so it can return the following:\n\n    -- in more recent browsers\n    Name \"Europe/Moscow\"\n\n    Name \"America/Havana\"\n\n    -- in older browsers\n    Offset 180\n\n    Offset -300\n\nSo if the real info is not available, it will tell you the current UTC offset\nin minutes, just like what `here` uses to make zones like `customZone -60 []`.\n\n","args":[],"cases":[["Name",["String.String"]],["Offset",["Basics.Int"]]]}],"aliases":[{"name":"Month","comment":" Represents a `Month` so that you can convert it to a `String` or `Int`\nhowever you please. For example, if you need the Danish representation, you\ncan say:\n\n    toDanishMonth : Month -> String\n    toDanishMonth month =\n        case month of\n            Jan ->\n                \"januar\"\n\n            Feb ->\n                \"februar\"\n\n            Mar ->\n                \"marts\"\n\n            Apr ->\n                \"april\"\n\n            May ->\n                \"maj\"\n\n            Jun ->\n                \"juni\"\n\n            Jul ->\n                \"juli\"\n\n            Aug ->\n                \"august\"\n\n            Sep ->\n                \"september\"\n\n            Oct ->\n                \"oktober\"\n\n            Nov ->\n                \"november\"\n\n            Dec ->\n                \"december\"\n\n","args":[],"type":"Time.Month"},{"name":"Posix","comment":" A computer representation of time. It is the same all over Earth, so if we\nhave a phone call or meeting at a certain POSIX time, there is no ambiguity.\n\nIt is very hard for humans to _read_ a POSIX time though, so we use functions\nlike [`toHour`](#toHour) and [`toMinute`](#toMinute) to `view` them.\n\n","args":[],"type":"Time.Posix"},{"name":"Weekday","comment":" Represents a `Weekday` so that you can convert it to a `String` or `Int`\nhowever you please. For example, if you need the Japanese representation, you\ncan say:\n\n    toJapaneseWeekday : Weekday -> String\n    toJapaneseWeekday weekday =\n        case weekday of\n            Mon ->\n                \"月\"\n\n            Tue ->\n                \"火\"\n\n            Wed ->\n                \"水\"\n\n            Thu ->\n                \"木\"\n\n            Fri ->\n                \"金\"\n\n            Sat ->\n                \"土\"\n\n            Sun ->\n                \"日\"\n\n","args":[],"type":"Time.Weekday"},{"name":"Zone","comment":" Information about a particular time zone.\n\nThe [IANA Time Zone Database][iana] tracks things like UTC offsets and\ndaylight-saving rules so that you can turn a `Posix` time into local times\nwithin a time zone.\n\nSee [`utc`](#utc), [`here`](#here), and [`Browser.Env`][env] to learn how to\nobtain `Zone` values.\n\n[iana]: https://www.iana.org/time-zones\n[env]: /packages/elm/browser/latest/Browser#Env\n\n","args":[],"type":"Time.Zone"}],"values":[{"name":"customZone","comment":" **Intended for package authors.**\n\nThe documentation of [`here`](#here) explains that it has certain accuracy\nlimitations that block on adding new APIs to JavaScript. The `customZone`\nfunction is a stopgap that takes:\n\n1.  A default offset in minutes. So `Etc/GMT-5` is `customZone (-5 * 60) []`\n    and `Etc/GMT+9` is `customZone (9 * 60) []`.\n2.  A list of exceptions containing their `start` time in \"minutes since the Unix\n    epoch\" and their `offset` in \"minutes from UTC\"\n\nHuman times will be based on the nearest `start`, falling back on the default\noffset if the time is older than all of the exceptions.\n\nWhen paired with `getZoneName`, this allows you to load the real IANA time zone\ndatabase however you want: HTTP, cache, hardcode, etc.\n\n**Note:** If you use this, please share your work in an Elm community forum!\nI am sure others would like to hear about it, and more experience reports will\nhelp me and the any potential TC39 proposal.\n\n","type":"Basics.Int -> List.List { start : Basics.Int, offset : Basics.Int } -> Effect.Time.Zone"},{"name":"every","comment":" Get the current time periodically. How often though? Well, you provide an\ninterval in milliseconds (like `1000` for a second or `60 * 1000` for a minute\nor `60 * 60 * 1000` for an hour) and that is how often you get a new time!\n\nCheck out [this example](https://elm-lang.org/examples/time) to see how to use\nit in an application.\n\n**This function is not for animation.** Use the [`elm/animation-frame`][af]\npackage for that sort of thing! It syncs up with repaints and will end up\nbeing much smoother for any moving visuals.\n\n[af]: /packages/elm/animation-frame/latest\n\n","type":"Duration.Duration -> (Effect.Time.Posix -> msg) -> Effect.Subscription.Subscription restriction msg"},{"name":"getZoneName","comment":" **Intended for package authors.**\n\nUse `Intl.DateTimeFormat().resolvedOptions().timeZone` to try to get names\nlike `Europe/Moscow` or `America/Havana`. From there you can look it up in any\nIANA data you loaded yourself.\n\n","type":"Effect.Task.Task Effect.Command.FrontendOnly x Effect.Time.ZoneName"},{"name":"here","comment":" Produce a `Zone` based on the current UTC offset. You can use this to figure\nout what day it is where you are:\n\n    import Task exposing (Task)\n    import Time\n\n    whatDayIsIt : Task x Int\n    whatDayIsIt =\n        Task.map2 Time.toDay Time.here Time.now\n\n**Accuracy Note:** This function can only give time zones like `Etc/GMT+9` or\n`Etc/GMT-6`. It cannot give you `Europe/Stockholm`, `Asia/Tokyo`, or any other\nnormal time zone from the [full list][tz] due to limitations in JavaScript.\nFor example, if you run `here` in New York City, the resulting `Zone` will\nnever be `America/New_York`. Instead you get `Etc/GMT-5` or `Etc/GMT-4`\ndepending on Daylight Saving Time. So even though browsers must have internal\naccess to `America/New_York` to figure out that offset, there is no public API\nto get the full information. This means the `Zone` you get from this function\nwill act weird if (1) an application stays open across a Daylight Saving Time\nboundary or (2) you try to use it on historical data.\n\n**Future Note:** We can improve `here` when there is good browser support for\nJavaScript functions that (1) expose the IANA time zone database and (2) let\nyou ask the time zone of the computer. The committee that reviews additions to\nJavaScript is called TC39, and I encourage you to push for these capabilities! I\ncannot do it myself unfortunately.\n\n**Alternatives:** See the `customZone` docs to learn how to implement stopgaps.\n\n[tz]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\n\n","type":"Effect.Task.Task Effect.Command.FrontendOnly x Effect.Time.Zone"},{"name":"millisToPosix","comment":" Turn milliseconds into a `Posix` time.\n","type":"Basics.Int -> Effect.Time.Posix"},{"name":"now","comment":" Get the POSIX time at the moment when this task is run.\n","type":"Effect.Task.Task restriction x Effect.Time.Posix"},{"name":"posixToMillis","comment":" Turn a `Posix` time into the number of milliseconds since 1970 January 1\nat 00:00:00 UTC. It was a Thursday.\n","type":"Effect.Time.Posix -> Basics.Int"},{"name":"toDay","comment":" What day is it?! (Days go from 1 to 31)\n\n    import Time exposing (toDay, utc, millisToPosix)\n\n    toDay utc (millisToPosix 0) == 1\n    toDay nyc (millisToPosix 0) == 31\n\n    -- pretend `nyc` is the `Zone` for America/New_York.\n\n","type":"Effect.Time.Zone -> Effect.Time.Posix -> Basics.Int"},{"name":"toHour","comment":" What hour is it? (From 0 to 23)\n\n    import Time exposing (toHour, utc, millisToPosix)\n\n    toHour utc (millisToPosix 0) == 0  -- 12am\n    toHour nyc (millisToPosix 0) == 19 -- 7pm\n\n    -- pretend `nyc` is the `Zone` for America/New_York.\n\n","type":"Effect.Time.Zone -> Effect.Time.Posix -> Basics.Int"},{"name":"toMillis","comment":"\n\n    import Time exposing (toMillis, utc, millisToPosix)\n\n    toMillis utc (millisToPosix    0) == 0\n    toMillis utc (millisToPosix 1234) == 234\n    toMillis utc (millisToPosix 5678) == 678\n\n","type":"Effect.Time.Zone -> Effect.Time.Posix -> Basics.Int"},{"name":"toMinute","comment":" What minute is it? (From 0 to 59)\n\n    import Time exposing (toMinute, utc, millisToPosix)\n\n    toMinute utc (millisToPosix 0) == 0\n\nThis can be different in different time zones. Some time zones are offset\nby 30 or 45 minutes!\n\n","type":"Effect.Time.Zone -> Effect.Time.Posix -> Basics.Int"},{"name":"toMonth","comment":" What month is it?!\n\n    import Time exposing (toMonth, utc, millisToPosix)\n\n    toMonth utc (millisToPosix 0) == Jan\n    toMonth nyc (millisToPosix 0) == Dec\n\n    -- pretend `nyc` is the `Zone` for America/New_York.\n\n","type":"Effect.Time.Zone -> Effect.Time.Posix -> Effect.Time.Month"},{"name":"toSecond","comment":" What second is it?\n\n    import Time exposing (toSecond, utc, millisToPosix)\n\n    toSecond utc (millisToPosix    0) == 0\n    toSecond utc (millisToPosix 1234) == 1\n    toSecond utc (millisToPosix 5678) == 5\n\n","type":"Effect.Time.Zone -> Effect.Time.Posix -> Basics.Int"},{"name":"toWeekday","comment":" What day of the week is it?\n\n    import Time exposing (toWeekday, utc, millisToPosix)\n\n    toWeekday utc (millisToPosix 0) == Thu\n    toWeekday nyc (millisToPosix 0) == Wed\n\n    -- pretend `nyc` is the `Zone` for America/New_York.\n\n","type":"Effect.Time.Zone -> Effect.Time.Posix -> Effect.Time.Weekday"},{"name":"toYear","comment":" What year is it?!\n\n    import Time exposing (toYear, utc, millisToPosix)\n\n    toYear utc (millisToPosix 0) == 1970\n    toYear nyc (millisToPosix 0) == 1969\n\n    -- pretend `nyc` is the `Zone` for America/New_York.\n\n","type":"Effect.Time.Zone -> Effect.Time.Posix -> Basics.Int"},{"name":"utc","comment":" The time zone for Coordinated Universal Time ([UTC])\n\nThe `utc` zone has no time adjustments. It never observes daylight-saving\ntime and it never shifts around based on political restructuring.\n\n[UTC]: https://en.wikipedia.org/wiki/Coordinated_Universal_Time\n\n","type":"Effect.Time.Zone"}],"binops":[]},{"name":"Effect.WebGL","comment":" The WebGL API is for high performance rendering. Definitely read about\n[how WebGL works](https://package.elm-lang.org/packages/elm-explorations/webgl/latest)\nand look at [some examples](https://github.com/elm-explorations/webgl/tree/main/examples)\nbefore trying to do too much with just the documentation provided here.\n\n\n# Mesh\n\n@docs Mesh, triangles\n\n\n# Shaders\n\n@docs Shader\n\n\n# Entities\n\n@docs Entity, entity\n\n\n# WebGL Html\n\n@docs toHtml\n\n\n# Advanced Usage\n\n@docs entityWith, toHtmlWith, Option, alpha, depth, stencil, antialias\n@docs clearColor, preserveDrawingBuffer\n\n\n# Meshes\n\n@docs indexedTriangles, lines, lineStrip, lineLoop, points, triangleFan\n@docs triangleStrip\n\n\n# Virtual Reality (aka webxr)\n\n@docs renderXrFrame, requestXrStart, XrPose, XrRenderError, XrStartError, XrView, XrEyeType, XrButton, XrHandedness, XrInput, XrStartData, endXrSession\n\n","unions":[{"name":"XrEyeType","comment":" ","args":[],"cases":[["LeftEye",[]],["RightEye",[]],["OtherEye",[]]]},{"name":"XrHandedness","comment":" ","args":[],"cases":[["LeftHand",[]],["RightHand",[]],["Unknown",[]]]},{"name":"XrRenderError","comment":" ","args":[],"cases":[["XrSessionNotStarted",[]],["XrLostTracking",[]]]},{"name":"XrStartError","comment":" ","args":[],"cases":[["AlreadyStarted",[]],["NotSupported",[]]]}],"aliases":[{"name":"Entity","comment":" Conceptually, an encapsulation of the instructions to render something.\n","args":[],"type":"WebGLFix.Entity"},{"name":"Mesh","comment":" Mesh forms geometry from the specified vertices. Each vertex contains a\nbunch of attributes, defined as a custom record type, e.g.:\n\n    type alias Attributes =\n        { position : Vec3\n        , color : Vec3\n        }\n\nThe supported types in attributes are: `Int`, `Float`, `Texture`\nand `Vec2`, `Vec3`, `Vec4`, `Mat4` from the\n[linear-algebra](https://package.elm-lang.org/packages/elm-explorations/linear-algebra/latest)\npackage.\n\nDo not generate meshes in `view`, [read more about this here](https://package.elm-lang.org/packages/elm-explorations/webgl/latest#making-the-most-of-the-gpu).\n\n","args":["attributes"],"type":"WebGL.Mesh attributes"},{"name":"Option","comment":" Provides a way to enable features and change the scene behavior\nin [`toHtmlWith`](#toHtmlWith).\n","args":[],"type":"WebGLFix.Option"},{"name":"Shader","comment":" Shaders are programs for running many computations on the GPU in parallel.\nThey are written in a language called\n[GLSL](https://en.wikipedia.org/wiki/OpenGL_Shading_Language). Read more about\nshaders [here](https://github.com/elm-explorations/webgl/blob/main/README.md).\n\nNormally you specify a shader with a `[glsl| |]` block. Elm compiler will parse\nthe shader code block and derive the type signature for your shader.\n\n  - `attributes` define vertices in the [mesh](#Mesh);\n  - `uniforms` allow you to pass scene parameters like\n    transformation matrix, texture, screen size, etc.;\n  - `varyings` define the output from the vertex shader.\n\n`attributes`, `uniforms` and `varyings` are records with the fields of the\nfollowing types: `Int`, `Float`, [`Texture`](#Texture) and `Vec2`, `Vec3`, `Vec4`,\n`Mat4` from the\n[linear-algebra](https://package.elm-lang.org/packages/elm-explorations/linear-algebra/latest)\npackage.\n\n","args":["attributes","uniforms","varyings"],"type":"WebGLFix.Shader attributes uniforms varyings"},{"name":"XrButton","comment":" ","args":[],"type":"{ isPressed : Basics.Bool, isTouched : Basics.Bool, value : Basics.Float }"},{"name":"XrInput","comment":" ","args":[],"type":"{ handedness : Effect.WebGL.XrHandedness, matrix : Maybe.Maybe Math.Matrix4.Mat4, buttons : List.List Effect.WebGL.XrButton, axes : List.List Basics.Float, mapping : String.String }"},{"name":"XrPose","comment":" ","args":[],"type":"{ transform : Math.Matrix4.Mat4, views : List.List Effect.WebGL.XrView, time : Effect.Time.Posix, boundary : Maybe.Maybe (List.List Math.Vector2.Vec2), inputs : List.List Effect.WebGL.XrInput }"},{"name":"XrStartData","comment":" ","args":[],"type":"{ boundary : Maybe.Maybe (List.List Math.Vector2.Vec2), supportedFrameRates : List.List Basics.Int }"},{"name":"XrView","comment":" ","args":[],"type":"{ eye : Effect.WebGL.XrEyeType, viewMatrix : Math.Matrix4.Mat4, projectionMatrix : Math.Matrix4.Mat4 }"}],"values":[{"name":"alpha","comment":" Enable alpha channel in the drawing buffer. If the argument is `True`, then\nthe page compositor will assume the drawing buffer contains colors with\npremultiplied alpha `(r * a, g * a, b * a, a)`.\n","type":"Basics.Bool -> Effect.WebGL.Option"},{"name":"antialias","comment":" Enable multisample antialiasing of the drawing buffer, if supported by\nthe platform. Useful when you need to have smooth lines and smooth edges of\ntriangles at a lower cost than supersampling (rendering to larger dimensions and\nthen scaling down with CSS transform).\n","type":"Effect.WebGL.Option"},{"name":"clearColor","comment":" Set the red, green, blue and alpha channels, that will be used to\nfill the drawing buffer every time before drawing the scene. The values are\nclamped between 0 and 1. The default is all 0's.\n","type":"Basics.Float -> Basics.Float -> Basics.Float -> Basics.Float -> Effect.WebGL.Option"},{"name":"depth","comment":" Enable the depth buffer, and prefill it with given value each time before\nthe scene is rendered. The value is clamped between 0 and 1.\n","type":"Basics.Float -> Effect.WebGL.Option"},{"name":"endXrSession","comment":" ","type":"Effect.Internal.Task Effect.Command.FrontendOnly x ()"},{"name":"entity","comment":" Packages a vertex shader, a fragment shader, a mesh, and uniforms\nas an `Entity`. This specifies a full rendering pipeline to be run\non the GPU. You can read more about the pipeline\n[here](https://github.com/elm-explorations/webgl/blob/main/README.md).\n\nThe vertex shader receives `attributes` and `uniforms` and returns `varyings`\nand `gl_Position`—the position of the vertex on the screen, defined as\n`vec4(x, y, z, w)`, that means `(x/w, y/w, z/w)` in the clip space coordinates:\n\n    --   (-1,1,1) +================+ (1,1,1)\n    --           /|               /|\n    --          / |     |        / |\n    --(-1,1,-1)+================+ (1,1,-1)\n    --         |  |     | /     |  |\n    --         |  |     |/      |  |\n    --         |  |     +-------|->|\n    -- (-1,-1,1|) +--(0,0,0)----|--+ (1,-1,1)\n    --         | /              | /\n    --         |/               |/\n    --         +================+\n    --   (-1,-1,-1)         (1,-1,-1)\n\n\n\nThe fragment shader is called for each pixel inside the clip space with\n`varyings` and `uniforms` and returns `gl_FragColor`—the color of\nthe pixel, defined as `vec4(r, g, b, a)` where each color component is a float\nfrom 0 to 1.\n\nShaders and a mesh are cached so that they do not get resent to the GPU.\nIt should be relatively cheap to create new entities out of existing\nvalues.\n\nBy default, [depth test](WebGL-Settings-DepthTest#default) is enabled for you.\nIf you need more [settings](WebGL-Settings), like\n[blending](WebGL-Settings-Blend) or [stencil test](WebG-Settings-StencilTest),\nthen use [`entityWith`](#entityWith).\n\n    entity =\n        entityWith [ DepthTest.default ]\n\n","type":"Effect.WebGL.Shader attributes uniforms varyings -> Effect.WebGL.Shader {} uniforms varyings -> Effect.WebGL.Mesh attributes -> uniforms -> Effect.WebGL.Entity"},{"name":"entityWith","comment":" The same as [`entity`](#entity), but allows to configure an entity with\n[settings](WebGL-Settings).\n","type":"List.List WebGL.Settings.Setting -> Effect.WebGL.Shader attributes uniforms varyings -> Effect.WebGL.Shader {} uniforms varyings -> Effect.WebGL.Mesh attributes -> uniforms -> Effect.WebGL.Entity"},{"name":"indexedTriangles","comment":" Create triangles from vertices and indices, grouped in sets of three to\ndefine each triangle by refering the vertices. This helps to avoid duplicated vertices whenever two triangles share an\nedge.\n\n    -- v2 +---+ v1\n    --    |\\  |\n    --    | \\ |\n    --    |  \\|\n    -- v3 +---+ v0\n\n\n\nFor example, if you want to define a rectangle using\n[`triangles`](#triangles), `v0` and `v2` will have to be duplicated:\n\n    rectangle =\n        triangles [ ( v0, v1, v2 ), ( v2, v3, v0 ) ]\n\nThis will use two vertices less:\n\n    rectangle =\n        indexedTriangles [ v0, v1, v2, v3 ] [ ( 0, 1, 2 ), ( 2, 3, 0 ) ]\n\n","type":"List.List attributes -> List.List ( Basics.Int, Basics.Int, Basics.Int ) -> Effect.WebGL.Mesh attributes"},{"name":"lineLoop","comment":" Similar to [`lineStrip`](#lineStrip), but connects the last vertex back to\nthe first.\n","type":"List.List attributes -> Effect.WebGL.Mesh attributes"},{"name":"lineStrip","comment":" Connects each two subsequent vertices with a line.\n","type":"List.List attributes -> Effect.WebGL.Mesh attributes"},{"name":"lines","comment":" Connects each pair of vertices with a line.\n","type":"List.List ( attributes, attributes ) -> Effect.WebGL.Mesh attributes"},{"name":"points","comment":" Draws a single dot per vertex.\n","type":"List.List attributes -> Effect.WebGL.Mesh attributes"},{"name":"preserveDrawingBuffer","comment":" By default, WebGL canvas swaps the drawing and display buffers.\nThis option forces it to copy the drawing buffer into the display buffer.\n\nEven though this slows down the rendering, it allows you to extract an image\nfrom the canvas element using `canvas.toBlob()` in JavaScript without having\nto worry about synchronization between frames.\n\n","type":"Effect.WebGL.Option"},{"name":"renderXrFrame","comment":" ","type":"({ time : Effect.Time.Posix, xrView : Effect.WebGL.XrView, inputs : List.List Effect.WebGL.XrInput } -> List.List Effect.WebGL.Entity) -> Effect.Task.Task Effect.Command.FrontendOnly Effect.WebGL.XrRenderError Effect.WebGL.XrPose"},{"name":"requestXrStart","comment":" ","type":"List.List WebGLFix.Option -> Effect.Task.Task Effect.Command.FrontendOnly Effect.WebGL.XrStartError Effect.WebGL.XrStartData"},{"name":"stencil","comment":" Enable the stencil buffer, specifying the index used to fill the\nstencil buffer before we render the scene. The index is masked with 2^m - 1,\nwhere m >= 8 is the number of bits in the stencil buffer. The default is 0.\n","type":"Basics.Int -> Effect.WebGL.Option"},{"name":"toHtml","comment":" Render a WebGL scene with the given html attributes, and entities.\n\n`width` and `height` html attributes resize the drawing buffer, while\nthe corresponding css properties scale the canvas element.\n\nTo prevent blurriness on retina screens, you may want the drawing buffer\nto be twice the size of the canvas element.\n\nTo remove an extra whitespace around the canvas, set `display: block`.\n\nBy default, alpha channel with premultiplied alpha, antialias and depth buffer\nare enabled. Use [`toHtmlWith`](#toHtmlWith) for custom options.\n\n    toHtml =\n        toHtmlWith [ alpha True, antialias, depth 1 ]\n\n","type":"List.List (Html.Attribute msg) -> List.List Effect.WebGL.Entity -> Html.Html msg"},{"name":"toHtmlWith","comment":" Render a WebGL scene with the given options, html attributes, and entities.\n\nDue to browser limitations, options will be applied only once,\nwhen the canvas is created for the first time.\n\n","type":"List.List Effect.WebGL.Option -> List.List (Html.Attribute msg) -> List.List Effect.WebGL.Entity -> Html.Html msg"},{"name":"triangleFan","comment":" Similar to [`triangleStrip`](#triangleStrip), but creates a fan shaped\noutput.\n","type":"List.List attributes -> Effect.WebGL.Mesh attributes"},{"name":"triangleStrip","comment":" Creates a strip of triangles where each additional vertex creates an\nadditional triangle once the first three vertices have been drawn.\n","type":"List.List attributes -> Effect.WebGL.Mesh attributes"},{"name":"triangles","comment":" Triangles are the basic building blocks of a mesh. You can put them together\nto form any shape.\n\nSo when you create `triangles` you are really providing three sets of attributes\nthat describe the corners of each triangle.\n\n","type":"List.List ( attributes, attributes, attributes ) -> Effect.WebGL.Mesh attributes"}],"binops":[]},{"name":"Effect.WebGL.Settings","comment":"\n\n\n# Settings\n\n@docs Setting, scissor, colorMask, polygonOffset, sampleAlphaToCoverage\n@docs sampleCoverage, cullFace\n\n\n## Face Modes\n\n@docs FaceMode, front, back, frontAndBack\n\n","unions":[],"aliases":[{"name":"FaceMode","comment":" Targets the polygons based on their facing.\n","args":[],"type":"WebGL.Settings.FaceMode"},{"name":"Setting","comment":" Lets you customize how an [`Entity`](WebGL#Entity) is rendered. So if you\nonly want to see the red part of your entity, you would use\n[`entityWith`](WebGL#entityWith) and [`colorMask`](#colorMask) to say:\n\n    entityWith [colorMask True False False False]\n        vertShader fragShader mesh uniforms\n\n    -- vertShader : Shader attributes uniforms varyings\n    -- fragShader : Shader {} uniforms varyings\n    -- mesh : Mesh attributes\n    -- uniforms : uniforms\n\n","args":[],"type":"WebGL.Settings.Setting"}],"values":[{"name":"back","comment":" ","type":"Effect.WebGL.Settings.FaceMode"},{"name":"colorMask","comment":" Specify whether or not each channel (red, green, blue, alpha) should be\noutput on the screen.\n","type":"Basics.Bool -> Basics.Bool -> Basics.Bool -> Basics.Bool -> Effect.WebGL.Settings.Setting"},{"name":"cullFace","comment":" Excludes polygons based on winding (the order of the vertices) in window\ncoordinates. Polygons with counter-clock-wise winding are front-facing.\n","type":"Effect.WebGL.Settings.FaceMode -> Effect.WebGL.Settings.Setting"},{"name":"front","comment":" ","type":"Effect.WebGL.Settings.FaceMode"},{"name":"frontAndBack","comment":" ","type":"Effect.WebGL.Settings.FaceMode"},{"name":"polygonOffset","comment":" When you want to draw the highlighting wireframe on top of the solid\nobject, the lines may fade in and out of the coincident polygons,\nwhich is sometimes called \"stitching\" and is visually unpleasant.\n\n[Polygon Offset](https://www.glprogramming.com/red/chapter06.html#name4)\nhelps to avoid \"stitching\" by adding an offset to pixel’s depth\nvalues before the depth test is performed and before the value is written\ninto the depth buffer.\n\n    polygonOffset factor units\n\nThis adds an `offset = m * factor + r * units`, where\n\n  - `m = max (dz / dx) (dz / dy)` is the maximum depth slope of the polygon.\n    The depth slope is the change in `z` (depth) values divided by the change in\n    either `x` or `y` coordinates, as you traverse a polygon;\n  - `r` is the smallest value guaranteed to produce a resolvable difference in\n    window coordinate depth values. The value `r` is an implementation-specific\n    constant.\n\nThe question is: \"How much offset is enough?\". It really depends on the slope.\nFor polygons that are parallel to the near and far clipping planes,\nthe depth slope is zero, so the minimum offset is needed:\n\n    polygonOffset 0 1\n\nFor polygons that are at a great angle to the clipping planes, the depth slope\ncan be significantly greater than zero. Use small non-zero values for factor,\nsuch as `0.75` or `1.0` should be enough to generate distinct depth values:\n\n    polygonOffset 0.75 1\n\n","type":"Basics.Float -> Basics.Float -> Effect.WebGL.Settings.Setting"},{"name":"sampleAlphaToCoverage","comment":" When you render overlapping transparent entities, like grass or hair, you\nmay notice that alpha blending doesn’t really work with depth testing, because\ndepth test ignores transparency.\n[Alpha To Coverage](https://wiki.polycount.com/wiki/Transparency_map#Alpha_To_Coverage)\nis a way to address this issue without sorting transparent entities.\n\nIt works by computing a temporary coverage value, where each bit is determined\nby the alpha value at the corresponding sample location. The temporary coverage\nvalue is then ANDed with the fragment coverage value.\n\nRequires [`WebGL.antialias`](WebGL#antialias) option.\n\n","type":"Effect.WebGL.Settings.Setting"},{"name":"sampleCoverage","comment":" Specifies multisample coverage parameters. The fragment's coverage is ANDed\nwith the temporary coverage value.\n\n  - the first argument specifies sample coverage value, that is clamped to the\n    range from 0 to 1;\n  - the second argument represents if the coverage masks should be inverted.\n\nRequires [`WebGL.antialias`](WebGL#antialias) option.\n\n","type":"Basics.Float -> Basics.Bool -> Effect.WebGL.Settings.Setting"},{"name":"scissor","comment":" Set the scissor box, which limits the drawing of fragments to the\nscreen to a specified rectangle.\n\nThe arguments are the coordinates of the lower left corner, width and height.\n\n","type":"Basics.Int -> Basics.Int -> Basics.Int -> Basics.Int -> Effect.WebGL.Settings.Setting"}],"binops":[]},{"name":"Effect.WebGL.Settings.Blend","comment":"\n\n\n# Blenders\n\n@docs add, subtract, reverseSubtract\n\n\n# Blend Factors\n\n@docs Factor, zero, one, srcColor, oneMinusSrcColor, dstColor\n@docs oneMinusDstColor, srcAlpha, oneMinusSrcAlpha, dstAlpha\n@docs oneMinusDstAlpha, srcAlphaSaturate\n\n\n# Custom Blenders\n\n@docs custom, Blender, customAdd, customSubtract, customReverseSubtract\n@docs constantColor, oneMinusConstantColor, constantAlpha\n@docs oneMinusConstantAlpha\n\n","unions":[],"aliases":[{"name":"Blender","comment":" A `Blender` mixes the color of the current `Entity` (the source color)\nwith whatever is behind it (the destination color).\nYou can get a feel for all the options [here](https://threejs.org/examples/webgl_materials_blending_custom.html).\n","args":[],"type":"WebGL.Settings.Blend.Blender"},{"name":"Factor","comment":" ","args":[],"type":"WebGL.Settings.Blend.Factor"}],"values":[{"name":"add","comment":" Add the color of the current `Renderable` (the source color)\nwith whatever is behind it (the destination color). For example,\nhere is the “default” blender:\n\n    add one zero\n\nThe resulting color will be `(src * 1) + (dest * 0)`, which means\nwe do not use the destination color at all!\nYou can get a feel for all the different blending factors\n[here](https://threejs.org/examples/webgl_materials_blending_custom.html).\n\n","type":"Effect.WebGL.Settings.Blend.Factor -> Effect.WebGL.Settings.Blend.Factor -> WebGL.Settings.Setting"},{"name":"constantAlpha","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"constantColor","comment":" This uses the constant `r`, `g`, `b`, and `a` values\ngiven to [`custom`](#custom). If you use this `Factor` with\n[`add`](#add), the constant color will default to black.\n\nBecause of\n[restriction in WebGL](https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.13),\nyou cannot create a `Blender`, that has one factor set to\n`constantColor` or `oneMinusConstantColor` and another set to\n`constantAlpha` or `oneMinusConstantAlpha`.\n\n","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"custom","comment":" It is possible to do some very fancy blending with\n`custom`. For example, you can blend the color value and\nthe alpha values separately:\n\n    myBlender : Float -> Setting\n    myBlender alpha =\n        custom\n            { r = 0\n            , g = 0\n            , b = 0\n            , a = alpha\n            , color = customAdd one zero\n            , alpha = customAdd one constantAlpha\n            }\n\n","type":"{ r : Basics.Float, g : Basics.Float, b : Basics.Float, a : Basics.Float, color : Effect.WebGL.Settings.Blend.Blender, alpha : Effect.WebGL.Settings.Blend.Blender } -> WebGL.Settings.Setting"},{"name":"customAdd","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor -> Effect.WebGL.Settings.Blend.Factor -> Effect.WebGL.Settings.Blend.Blender"},{"name":"customReverseSubtract","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor -> Effect.WebGL.Settings.Blend.Factor -> Effect.WebGL.Settings.Blend.Blender"},{"name":"customSubtract","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor -> Effect.WebGL.Settings.Blend.Factor -> Effect.WebGL.Settings.Blend.Blender"},{"name":"dstAlpha","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"dstColor","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"one","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"oneMinusConstantAlpha","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"oneMinusConstantColor","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"oneMinusDstAlpha","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"oneMinusDstColor","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"oneMinusSrcAlpha","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"oneMinusSrcColor","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"reverseSubtract","comment":" Similar to [`add`](#add), but it does `(dest * factor2) - (src * factor1)`.\nThis one is weird.\n","type":"Effect.WebGL.Settings.Blend.Factor -> Effect.WebGL.Settings.Blend.Factor -> WebGL.Settings.Setting"},{"name":"srcAlpha","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"srcAlphaSaturate","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"srcColor","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"},{"name":"subtract","comment":" Similar to [`add`](#add), but it does `(src * factor1) - (dest * factor2)`.\nFor example:\n\n    subtract one one\n\nThis would do `(src * 1) - (dest * 1)` so you would take away colors\nbased on the background.\n\n","type":"Effect.WebGL.Settings.Blend.Factor -> Effect.WebGL.Settings.Blend.Factor -> WebGL.Settings.Setting"},{"name":"zero","comment":" ","type":"Effect.WebGL.Settings.Blend.Factor"}],"binops":[]},{"name":"Effect.WebGL.Settings.DepthTest","comment":" You can read more about depth-testing in the\n[OpenGL wiki](https://www.khronos.org/opengl/wiki/Depth_Test)\nor [OpenGL docs](https://www.opengl.org/sdk/docs/man2/xhtml/glDepthFunc.xml).\n\n\n# Depth Test\n\n@docs default\n\n\n# Custom Tests\n\n@docs Options, less, never, always, equal, greater, notEqual\n@docs lessOrEqual, greaterOrEqual\n\n","unions":[],"aliases":[{"name":"Options","comment":" When rendering, you have a buffer of pixels. Depth-testing works by\ncreating a second buffer with exactly the same number of entries, but\ninstead of holding colors, each entry holds the distance from the camera.\nYou go through all your entities, writing into the depth buffer, and then\nyou draw the color of the “winner”.\n\nWhich color wins? This is based on a bunch of comparison functions:\n\n    less options -- value < depth\n\n    never options -- Never pass\n\n    always options -- Always pass\n\n    equal options -- value == depth\n\n    greater options -- value > depth\n\n    notEqual options -- value != depth\n\n    lessOrEqual options -- value <= depth\n\n    greaterOrEqual options -- value >= depth\n\nIf the test passes, the current value will be written into the depth buffer, so\nthe next pixels will be tested against it. Sometimes you may want to disable\nwriting. For example, when using depth test together with stencil test to create\n[reflection effect](https://open.gl/depthstencils) you want to draw the\nreflection _underneath_ the floor, in this case you set `write = False`\nwhen drawing the floor. The\n[crate example](https://github.com/elm-explorations/webgl/blob/main/examples/crate.elm)\nshows how to do it in Elm.\n\n`near` and `far` allow to allocate a portion of the depth range from 0 to 1.\nFor example, if you want to render GUI on top of the scene, you can\nset `near = 0.1, far = 1` for the scene and then render the GUI with\n`near = 0, far = 0.1`.\n\n","args":[],"type":"{ write : Basics.Bool, near : Basics.Float, far : Basics.Float }"}],"values":[{"name":"always","comment":" ","type":"Effect.WebGL.Settings.DepthTest.Options -> WebGL.Settings.Setting"},{"name":"default","comment":" With every pixel, we have to figure out which color to show.\n\nImagine you have many entities in the same line of sight. The floor,\nthen a table, then a plate. When depth-testing is off, you go through\nthe entities in the order they appear in your _code_! That means if\nyou describe the floor last, it will be “on top” of the table and plate.\n\nDepth-testing means the color is chosen based on the distance from the\ncamera. So `default` uses the color closest to the camera. This means\nthe plate will be on top of the table, and both are on top of the floor.\nSeems more reasonable!\n\nThere are a bunch of ways you can customize the depth test, shown later,\nand you can use them to define `default` like this:\n\n    default =\n        less { write = True, near = 0, far = 1 }\n\nRequires [`WebGL.depth`](WebGL#depth) option in\n[`toHtmlWith`](WebGL#toHtmlWith).\n\n","type":"WebGL.Settings.Setting"},{"name":"equal","comment":" ","type":"Effect.WebGL.Settings.DepthTest.Options -> WebGL.Settings.Setting"},{"name":"greater","comment":" ","type":"Effect.WebGL.Settings.DepthTest.Options -> WebGL.Settings.Setting"},{"name":"greaterOrEqual","comment":" ","type":"Effect.WebGL.Settings.DepthTest.Options -> WebGL.Settings.Setting"},{"name":"less","comment":" ","type":"Effect.WebGL.Settings.DepthTest.Options -> WebGL.Settings.Setting"},{"name":"lessOrEqual","comment":" ","type":"Effect.WebGL.Settings.DepthTest.Options -> WebGL.Settings.Setting"},{"name":"never","comment":" ","type":"Effect.WebGL.Settings.DepthTest.Options -> WebGL.Settings.Setting"},{"name":"notEqual","comment":" ","type":"Effect.WebGL.Settings.DepthTest.Options -> WebGL.Settings.Setting"}],"binops":[]},{"name":"Effect.WebGL.Settings.StencilTest","comment":" You can read more about stencil-testing in the\n[OpenGL wiki](https://www.khronos.org/opengl/wiki/Stencil_Test)\nor [OpenGL docs](https://www.opengl.org/sdk/docs/man2/xhtml/glStencilFunc.xml).\n\n\n# Stencil Test\n\n@docs test\n\n\n## Tests\n\n@docs Test, always, equal, never, less, greater, notEqual\n@docs lessOrEqual, greaterOrEqual\n\n\n## Operations\n\n@docs Operation, replace, keep, zero, increment, decrement, invert\n@docs incrementWrap, decrementWrap\n\n\n# Separate Test\n\n@docs testSeparate\n\n","unions":[],"aliases":[{"name":"Operation","comment":" Defines how to update the value in the stencil buffer.\n","args":[],"type":"WebGL.Settings.StencilTest.Operation"},{"name":"Test","comment":" The `Test` allows you to define how to compare the reference value\nwith the stencil buffer value, in order to set the conditions under which\nthe pixel will be drawn.\n\n    always -- Always pass\n\n    equal -- ref & mask == stencil & mask\n\n    never -- Never pass\n\n    less -- ref & mask < stencil & mask\n\n    greater -- ref & mask > stencil & mask\n\n    notEqual -- ref & mask != stencil & mask\n\n    lessOrEqual -- ref & mask <= stencil & mask\n\n    greaterOrEqual -- ref & mask >= stencil & mask\n\n","args":[],"type":"WebGL.Settings.StencilTest.Test"}],"values":[{"name":"always","comment":" ","type":"Effect.WebGL.Settings.StencilTest.Test"},{"name":"decrement","comment":" Decrements the current stencil buffer value. Clamps to 0.\n","type":"Effect.WebGL.Settings.StencilTest.Operation"},{"name":"decrementWrap","comment":" Decrements the current stencil buffer value.\nWraps stencil buffer value to the maximum representable unsigned\nvalue when decrementing a stencil buffer value of zero.\n","type":"Effect.WebGL.Settings.StencilTest.Operation"},{"name":"equal","comment":" ","type":"Effect.WebGL.Settings.StencilTest.Test"},{"name":"greater","comment":" ","type":"Effect.WebGL.Settings.StencilTest.Test"},{"name":"greaterOrEqual","comment":" ","type":"Effect.WebGL.Settings.StencilTest.Test"},{"name":"increment","comment":" Increments the current stencil buffer value. Clamps to the maximum\nrepresentable unsigned value.\n","type":"Effect.WebGL.Settings.StencilTest.Operation"},{"name":"incrementWrap","comment":" Increments the current stencil buffer value. Wraps stencil buffer value to\nzero when incrementing the maximum representable unsigned value.\n","type":"Effect.WebGL.Settings.StencilTest.Operation"},{"name":"invert","comment":" Bitwise inverts the current stencil buffer value.\n","type":"Effect.WebGL.Settings.StencilTest.Operation"},{"name":"keep","comment":" Keeps the current stencil buffer value. Use this as a noop.\n","type":"Effect.WebGL.Settings.StencilTest.Operation"},{"name":"less","comment":" ","type":"Effect.WebGL.Settings.StencilTest.Test"},{"name":"lessOrEqual","comment":" ","type":"Effect.WebGL.Settings.StencilTest.Test"},{"name":"never","comment":" ","type":"Effect.WebGL.Settings.StencilTest.Test"},{"name":"notEqual","comment":" ","type":"Effect.WebGL.Settings.StencilTest.Test"},{"name":"replace","comment":" Sets the stencil buffer value to `ref` from the stencil test.\n","type":"Effect.WebGL.Settings.StencilTest.Operation"},{"name":"test","comment":" When you need to draw an intercection of two entities, e.g. a reflection in\nthe mirror, you can test against the stencil buffer, that has to be enabled\nwith [`stencil`](WebGL#stencil) option in [`toHtmlWith`](WebGL#toHtmlWith).\n\nStencil test decides if the pixel should be drawn on the screen.\nDepending on the results, it performs one of the following\n[operations](#Operation) on the stencil buffer:\n\n  - `fail`—the operation to use when the stencil test fails;\n  - `zfail`—the operation to use when the stencil test passes, but the depth\n    test fails;\n  - `zpass`—the operation to use when both the stencil test and the depth test\n    pass, or when the stencil test passes and there is no depth buffer or depth\n    testing is disabled.\n\nFor example, draw the mirror `Entity` on the screen and fill the stencil buffer\nwith all 1's:\n\n    test\n        { ref = 1\n        , mask = 0xFF\n        , test = always -- pass for each pixel\n        , fail = keep -- noop\n        , zfail = keep -- noop\n        , zpass = replace -- write ref to the stencil buffer\n        , writeMask = 0xFF -- enable all stencil bits for writing\n        }\n\nCrop the reflection `Entity` using the values from the stencil buffer:\n\n    test\n        { ref = 1\n        , mask = 0xFF\n        , test = equal -- pass when the stencil value is equal to ref = 1\n        , fail = keep -- noop\n        , zfail = keep -- noop\n        , zpass = keep -- noop\n        , writeMask = 0 -- disable writing to the stencil buffer\n        }\n\nYou can see the complete example\n[here](https://github.com/elm-explorations/webgl/blob/main/examples/Crate.elm).\n\n","type":"{ ref : Basics.Int, mask : Basics.Int, test : Effect.WebGL.Settings.StencilTest.Test, fail : Effect.WebGL.Settings.StencilTest.Operation, zfail : Effect.WebGL.Settings.StencilTest.Operation, zpass : Effect.WebGL.Settings.StencilTest.Operation, writeMask : Basics.Int } -> WebGL.Settings.Setting"},{"name":"testSeparate","comment":" Different options for front and back facing polygons.\n","type":"{ ref : Basics.Int, mask : Basics.Int, writeMask : Basics.Int } -> { test : Effect.WebGL.Settings.StencilTest.Test, fail : Effect.WebGL.Settings.StencilTest.Operation, zfail : Effect.WebGL.Settings.StencilTest.Operation, zpass : Effect.WebGL.Settings.StencilTest.Operation } -> { test : Effect.WebGL.Settings.StencilTest.Test, fail : Effect.WebGL.Settings.StencilTest.Operation, zfail : Effect.WebGL.Settings.StencilTest.Operation, zpass : Effect.WebGL.Settings.StencilTest.Operation } -> WebGL.Settings.Setting"},{"name":"zero","comment":" Sets the stencil buffer value to 0.\n","type":"Effect.WebGL.Settings.StencilTest.Operation"}],"binops":[]},{"name":"Effect.WebGL.Texture","comment":"\n\n\n# Texture\n\n@docs Texture, load, Error, size\n\n\n# Custom Loading\n\n@docs loadWith, Options, defaultOptions, loadBytesWith, Format, rgb, rgba, alpha, luminance, luminanceAlpha\n\n\n## Resizing\n\n@docs Resize, linear, nearest\n@docs nearestMipmapLinear, nearestMipmapNearest\n@docs linearMipmapNearest, linearMipmapLinear\n@docs Bigger, Smaller\n\n\n## Wrapping\n\n@docs Wrap, repeat, clampToEdge, mirroredRepeat\n\n\n# Things You Shouldn’t Do\n\n@docs nonPowerOfTwoOptions\n\n","unions":[{"name":"Error","comment":" Loading a texture can result in two kinds of errors:\n\n  - `LoadError` means the image did not load for some reason. Maybe\n    it was a network problem, or maybe it was a bad file format.\n\n  - `SizeError` means you are trying to load a weird shaped image.\n    For most operations you want a rectangle where the width is a power\n    of two and the height is a power of two. This is more efficient on\n    the GPU and it makes mipmapping possible. You can use\n    [`nonPowerOfTwoOptions`](#nonPowerOfTwoOptions) to get things working\n    now, but it is way better to create power-of-two assets!\n\n","args":[],"cases":[["LoadError",[]],["SizeError",["Basics.Int","Basics.Int"]]]}],"aliases":[{"name":"Bigger","comment":" Helps restrict `options.magnify` to only allow\n[`linear`](#linear) and [`nearest`](#nearest).\n","args":[],"type":"Effect.Internal.Bigger"},{"name":"Format","comment":" How to read bytes into pixel\n\n\n## | Format | Channels | Bytes per pixel |\n\n| rgba | 4 | 4 |\n| rgb | 3 | 3 |\n| luminanceAlpha | 2 | 2 |\n| luminance | 1 | 1 |\n\n\n## | alpha | 1 | 1 |\n\n","args":[],"type":"WebGLFix.Texture.Format"},{"name":"Options","comment":" `Options` describe how to:\n\n  - `magnify` - how to [`Resize`](#Resize) into a bigger texture\n  - `minify` - how to [`Resize`](#Resize) into a smaller texture\n  - `horizontalWrap` - how to [`Wrap`](#Wrap) the texture horizontally if the width is not a power of two\n  - `verticalWrap` - how to [`Wrap`](#Wrap) the texture vertically if the height is not a power of two\n  - `flipY` - flip the Y axis of the texture so it has the same direction\n    as the clip-space, i.e. pointing up.\n\nYou can read more about these parameters in the\n[specification](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexParameter.xml).\n\n","args":[],"type":"{ magnify : Effect.WebGL.Texture.Resize Effect.WebGL.Texture.Bigger, minify : Effect.WebGL.Texture.Resize Effect.WebGL.Texture.Smaller, horizontalWrap : Effect.WebGL.Texture.Wrap, verticalWrap : Effect.WebGL.Texture.Wrap, flipY : Basics.Bool, premultiplyAlpha : Basics.Bool }"},{"name":"Resize","comment":" How to resize a texture.\n","args":["a"],"type":"Effect.Internal.Resize a"},{"name":"Smaller","comment":" Helps restrict `options.magnify`, while also allowing\n`options.minify` to use mipmapping resizes, like\n[`nearestMipmapNearest`](#nearestMipmapNearest).\n","args":[],"type":"Effect.Internal.Smaller"},{"name":"Texture","comment":" Use `Texture` to pass the `sampler2D` uniform value to the shader.\nYou can create a texture with [`load`](#load) or [`loadWith`](#loadWith)\nand measure its dimensions with [`size`](#size).\n","args":[],"type":"WebGLFix.Texture.Texture"},{"name":"Wrap","comment":" Sets the wrap parameter for texture coordinate.\n","args":[],"type":"Effect.Internal.Wrap"}],"values":[{"name":"alpha","comment":" Single pixel is 1 byte long and has 1 channel\n","type":"WebGLFix.Texture.Format"},{"name":"clampToEdge","comment":" Causes coordinates to be clamped to the range 1 2N 1 - 1 2N, where N is\nthe size of the texture in the direction of clamping.\n","type":"Effect.WebGL.Texture.Wrap"},{"name":"defaultOptions","comment":" Default options for the loaded texture.\n\n    { magnify = linear\n    , minify = nearestMipmapLinear\n    , horizontalWrap = repeat\n    , verticalWrap = repeat\n    , flipY = True\n    }\n\n","type":"Effect.WebGL.Texture.Options"},{"name":"linear","comment":" Returns the weighted average of the four texture elements that are closest\nto the center of the pixel being textured.\n","type":"Effect.WebGL.Texture.Resize a"},{"name":"linearMipmapLinear","comment":" Chooses the two mipmaps that most closely match the size of the pixel being\ntextured and uses the `linear` criterion (a weighted average of the four\ntexture elements that are closest to the center of the pixel) to produce a\ntexture value from each mipmap. The final texture value is a weighted average\nof those two values.\n","type":"Effect.WebGL.Texture.Resize Effect.WebGL.Texture.Smaller"},{"name":"linearMipmapNearest","comment":" Chooses the mipmap that most closely matches the size of the pixel being\ntextured and uses the `linear` criterion (a weighted average of the four\ntexture elements that are closest to the center of the pixel) to produce a\ntexture value.\n","type":"Effect.WebGL.Texture.Resize Effect.WebGL.Texture.Smaller"},{"name":"load","comment":" Loads a texture from the given url with default options.\nPNG and JPEG are known to work, but other formats have not been as\nwell-tested yet.\n\nThe Y axis of the texture is flipped automatically for you, so it has\nthe same direction as in the clip-space, i.e. pointing up.\n\nIf you need to change flipping, filtering or wrapping, you can use\n[`loadWith`](#loadWith).\n\n    load url =\n        loadWith defaultOptions url\n\n","type":"String.String -> Effect.Task.Task Effect.Command.FrontendOnly Effect.WebGL.Texture.Error Effect.WebGL.Texture.Texture"},{"name":"loadBytesWith","comment":" Building [`Texture`](#Texture) from bytes\n\n  - [`Options`](#Options) - same as for [`loadWith`](#loadWith)\n  - `(width, height)` - dimensions of new created texture\n  - [`Format`](#Format) - pixel format in bytes\n  - Bytes - encoded pixels, where `Bytes.width` > `width` \\* `height` \\* `Bytes per pixel` or you get `SizeError`\n    Do not generate texture in `view`, [read more about this here](https://package.elm-lang.org/packages/elm-explorations/webgl/latest#making-the-most-of-the-gpu).\n\n","type":"Effect.WebGL.Texture.Options -> ( Basics.Int, Basics.Int ) -> Effect.WebGL.Texture.Format -> Bytes.Bytes -> Result.Result Effect.WebGL.Texture.Error Effect.WebGL.Texture.Texture"},{"name":"loadWith","comment":" Same as load, but allows to set options.\n","type":"Effect.WebGL.Texture.Options -> String.String -> Effect.Task.Task Effect.Command.FrontendOnly Effect.WebGL.Texture.Error Effect.WebGL.Texture.Texture"},{"name":"luminance","comment":" Single pixel is 1 byte long and has 1 channel\n","type":"WebGLFix.Texture.Format"},{"name":"luminanceAlpha","comment":" Single pixel is 2 bytes long and has 2 channels\n","type":"WebGLFix.Texture.Format"},{"name":"mirroredRepeat","comment":" Causes the coordinate c to be set to the fractional part of the texture\ncoordinate if the integer part is even; if the integer part is odd, then\nthe coordinate is set to 1 - frac, where frac represents the fractional part\nof the coordinate.\n","type":"Effect.WebGL.Texture.Wrap"},{"name":"nearest","comment":" Returns the value of the texture element that is nearest\n(in Manhattan distance) to the center of the pixel being textured.\n","type":"Effect.WebGL.Texture.Resize a"},{"name":"nearestMipmapLinear","comment":" Chooses the two mipmaps that most closely match the size of the pixel being\ntextured and uses the `nearest` criterion (the texture element nearest to the\ncenter of the pixel) to produce a texture value from each mipmap. The final\ntexture value is a weighted average of those two values.\n","type":"Effect.WebGL.Texture.Resize Effect.WebGL.Texture.Smaller"},{"name":"nearestMipmapNearest","comment":" Chooses the mipmap that most closely matches the size of the pixel being\ntextured and uses the `nearest` criterion (the texture element nearest to\nthe center of the pixel) to produce a texture value.\n\nA mipmap is an ordered set of arrays representing the same image at\nprogressively lower resolutions.\n\nThis is the default value of the minify filter.\n\n","type":"Effect.WebGL.Texture.Resize Effect.WebGL.Texture.Smaller"},{"name":"nonPowerOfTwoOptions","comment":" The exact options needed to load textures with weird shapes.\nIf your image width or height is not a power of two, you need these\noptions:\n\n    { magnify = linear\n    , minify = nearest\n    , horizontalWrap = clampToEdge\n    , verticalWrap = clampToEdge\n    , flipY = True\n    }\n\n","type":"Effect.WebGL.Texture.Options"},{"name":"repeat","comment":" Causes the integer part of the coordinate to be ignored. This is the\ndefault value for both texture axis.\n","type":"Effect.WebGL.Texture.Wrap"},{"name":"rgb","comment":" Single pixel is 3 bytes long and has 3 channels\n","type":"WebGLFix.Texture.Format"},{"name":"rgba","comment":" Single pixel is 4 bytes long and has 4 channels\n","type":"WebGLFix.Texture.Format"},{"name":"size","comment":" Return the (width, height) size of a texture. Useful for sprite sheets\nor other times you may want to use only a potion of a texture image.\n","type":"Effect.WebGL.Texture.Texture -> ( Basics.Int, Basics.Int )"}],"binops":[]},{"name":"Effect.Websocket","comment":"\n\n@docs Connection, SendError, close, createHandle, listen, sendString, CloseEventCode\n\n","unions":[{"name":"CloseEventCode","comment":" Here are some possible reasons that your websocket connection closed.\n","args":[],"cases":[["NormalClosure",[]],["GoingAway",[]],["ProtocolError",[]],["UnsupportedData",[]],["NoStatusReceived",[]],["AbnormalClosure",[]],["InvalidFramePayloadData",[]],["PolicyViolation",[]],["MessageTooBig",[]],["MissingExtension",[]],["InternalError",[]],["ServiceRestart",[]],["TryAgainLater",[]],["BadGateway",[]],["TlsHandshake",[]],["UnknownCode",["Basics.Int"]]]},{"name":"Connection","comment":" A websocket connection\n","args":[],"cases":[]},{"name":"SendError","comment":" Errors that might happen when sending data.\n","args":[],"cases":[["ConnectionClosed",[]]]}],"aliases":[],"values":[{"name":"close","comment":" Close the websocket connection. This won't trigger any close notifications in `listen`.\n","type":"Effect.Websocket.Connection -> Effect.Task.Task restriction x ()"},{"name":"createHandle","comment":" Create a websocket handle that you can then open by calling `listen` or `sendString`.\nMake sure to call `close` when you are finished with it.\n","type":"(Effect.Websocket.Connection -> msg) -> String.String -> Effect.Command.Command restriction toMsg msg"},{"name":"listen","comment":" Listen for incoming messages through a websocket connection.\nYou'll also get notified if the connection closes unexpectedly (or in other words, you won't get notified if you're the one closing it with `close`).\n","type":"Effect.Websocket.Connection -> (String.String -> msg) -> ({ code : Effect.Websocket.CloseEventCode, reason : String.String } -> msg) -> Effect.Subscription.Subscription restriction msg"},{"name":"sendString","comment":" Send a string\n","type":"Effect.Websocket.Connection -> String.String -> Effect.Task.Task restriction Effect.Websocket.SendError ()"}],"binops":[]}]