diff --git a/docs.json b/docs.json index 3b6884c..0411b54 100644 --- a/docs.json +++ b/docs.json @@ -1 +1 @@ -[{"name":"Web","comment":" A state-interface program that can run in the browser\n\n@docs ProgramConfig, program, Program\n\nYou can also [embed](#embed) a state-interface program as part of an existing app that uses The Elm Architecture\n\n\n# interfaces\n\n@docs Interface, interfaceBatch, interfaceNone, interfaceFutureMap\n\n\n## DOM\n\nTypes used by [`Web.Dom`](Web-Dom)\n\n@docs DomNode, DomElement, DomElementVisibilityAlignment, DefaultActionHandling\n\n\n## Audio\n\nTypes used by [`Web.Audio`](Web-Audio)\n\n@docs Audio, AudioSource, AudioSourceLoadError, AudioProcessing, AudioParameterTimeline, EditAudioDiff\n\n\n## HTTP\n\nTypes used by [`Web.Http`](Web-Http)\n\n@docs HttpRequest, HttpBody, HttpExpect, HttpError, HttpMetadata\n\n\n## socket\n\nTypes used by [`Web.Socket`](Web-Socket)\n\n@docs SocketConnectionEvent, SocketId\n\n\n## geo location\n\nTypes used by [`Web.GeoLocation`](Web-GeoLocation)\n\n@docs GeoLocation\n\n\n## gamepads\n\nTypes used by [`Web.Gamepads`](Web-Gamepads)\n\n@docs Gamepad, GamepadButton\n\n\n## notification\n\nTypes used by [`Web.Notification`](Web-Notification)\n\n@docs NotificationClicked\n\n\n## window\n\nTypes used by [`Web.Window`](Web-Window)\n\n@docs WindowVisibility\n\n\n## embed\n\nIf you just want to replace a part of your elm app with this architecture. Make sure to wire in all 3:\n\n@docs programInit, programUpdate, programSubscriptions\n\nUnder the hood, [`Web.program`](Web#program) is then defined as just\n\n program config =\n Platform.worker\n { init = \\() -> Web.programInit yourAppConfig\n , update = Web.programUpdate yourAppConfig\n , subscriptions = Web.programSubscriptions yourAppConfig\n }\n\n\n## internals, safe to ignore for users\n\n@docs ProgramState, ProgramEvent\n@docs InterfaceSingle, InterfaceSingleWithFuture, InterfaceSingleRequest, InterfaceSingleListen, InterfaceSingleWithoutFuture\n@docs interfaceDiffs, findInterfaceAssociatedWithDiffComingBack, interfaceFutureJsonDecoder, InterfaceDiff, InterfaceWithFutureDiff, InterfaceWithoutFutureDiff, EditDomDiff, ReplacementInEditDomDiff, InterfaceSingleRequestId, InterfaceSingleListenId, DomElementId, DomNodeId, HttpRequestId, HttpExpectId\n\n","unions":[{"name":"AudioProcessing","comment":" A single effect filter applied to an [`Audio`](#Audio)\n","args":[],"cases":[["AudioLinearConvolution",["{ sourceUrl : String.String }"]],["AudioLowpass",["{ cutoffFrequency : Web.AudioParameterTimeline }"]],["AudioHighpass",["{ cutoffFrequency : Web.AudioParameterTimeline }"]]]},{"name":"AudioSourceLoadError","comment":" These are possible errors we can get when loading an audio source file.\n\n - `AudioSourceLoadDecodeError`: This means we got the data but we couldn't decode it. One likely reason for this is that your url points to the wrong place and you're trying to decode a 404 page instead.\n - `AudioSourceLoadNetworkError`: We couldn't reach the url. Either it's some kind of CORS issue, the server is down, or you're disconnected from the internet.\n - `AudioSourceLoadUnknownError`: the audio source didn't load for a reason I'm not aware of. If this occurs in your app, [open an issue](https://github.com/lue-bird/elm-state-interface/issues/new) with the reason string so a new variant can be added for this\n\n","args":[],"cases":[["AudioSourceLoadDecodeError",[]],["AudioSourceLoadNetworkError",[]],["AudioSourceLoadUnknownError",["String.String"]]]},{"name":"DefaultActionHandling","comment":" Setting for a listen [`Web.Dom.Modifier`](Web-Dom#Modifier) to keep or overwrite the browsers default action\n","args":[],"cases":[["DefaultActionPrevent",[]],["DefaultActionExecute",[]]]},{"name":"DomElementVisibilityAlignment","comment":" What part of the [`DomElement`](Web#DomElement) should be visible\n\n - `DomElementStart`: mostly for text to read\n - `DomElementEnd`: mostly for text to write\n - `DomElementCenter`: mostly for images\n\n","args":[],"cases":[["DomElementStart",[]],["DomElementEnd",[]],["DomElementCenter",[]]]},{"name":"DomNode","comment":" Plain text or a [`DomElement`](#DomElement) for use in an [`Interface`](#Interface).\n","args":["future"],"cases":[["DomText",["String.String"]],["DomElement",["Web.DomElement future"]]]},{"name":"DomNodeId","comment":" Safe to ignore. Identifier for a [`DomNode`](#DomNode)\n","args":[],"cases":[["DomTextId",["String.String"]],["DomElementId",["Web.DomElementId"]]]},{"name":"EditAudioDiff","comment":" What parts of an [`Audio`](#Audio) are replaced\n","args":[],"cases":[["ReplacementAudioVolume",["Web.AudioParameterTimeline"]],["ReplacementAudioSpeed",["Web.AudioParameterTimeline"]],["ReplacementAudioStereoPan",["Web.AudioParameterTimeline"]],["ReplacementAudioProcessing",["List.List Web.AudioProcessing"]]]},{"name":"GamepadButton","comment":" Buttons are either held down with an optional value between 0 and 1 to measure how hard,\nor they are released with an optional detection of touch which defaults to false.\n","args":[],"cases":[["GamepadButtonPressed",["{ firmnessPercentage : Basics.Float }"]],["GamepadButtonReleased",["{ isTouched : Basics.Bool }"]]]},{"name":"HttpBody","comment":" Data send in your http request.\n\n - `HttpBodyEmpty`: Create an empty body for your request.\n This is useful for `GET` requests and `POST` requests where you are not sending any data.\n\n - `HttpBodyString`: Put a `String` in the body of your request. Defining `Web.Http.jsonBody` looks like this:\n\n import Json.Encode\n\n jsonBody : Json.Encode.Value -> Web.HttpBody\n jsonBody value =\n Web.HttpBodyString \"application/json\" (Json.Encode.encode 0 value)\n\n The first argument is a [MIME type](https://en.wikipedia.org/wiki/Media_type) of the body.\n\n - `HttpBodyUnsignedInt8s` is pretty much the same as `HttpBodyString` but for [`Bytes`](https://dark.elm.dmy.fr/packages/elm/bytes/latest/),\n see [`Web.Http.bodyBytes`](Web-Http#bodyBytes)\n\n","args":[],"cases":[["HttpBodyEmpty",[]],["HttpBodyString",["{ mimeType : String.String, content : String.String }"]],["HttpBodyUnsignedInt8s",["{ mimeType : String.String, content : List.List Basics.Int }"]]]},{"name":"HttpError","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. Contains:\n - The response `Metadata`.\n - The raw response body as a `Json.Decode.Value`.\n\n","args":[],"cases":[["HttpBadUrl",["String.String"]],["HttpTimeout",[]],["HttpNetworkError",[]],["HttpBadStatus",["{ metadata : Web.HttpMetadata, body : Json.Decode.Value }"]]]},{"name":"HttpExpect","comment":" Describe what you expect to be returned in an http response body.\n","args":["future"],"cases":[["HttpExpectString",["Result.Result Web.HttpError String.String -> future"]],["HttpExpectBytes",["Result.Result Web.HttpError Bytes.Bytes -> future"]],["HttpExpectWhatever",["Result.Result Web.HttpError () -> future"]]]},{"name":"HttpExpectId","comment":" Safe to ignore. Identifier for an [`HttpExpect`](#HttpExpect)\n","args":[],"cases":[["IdHttpExpectString",[]],["IdHttpExpectBytes",[]],["IdHttpExpectWhatever",[]]]},{"name":"InterfaceDiff","comment":" Safe to ignore. Individual messages to js. Also used to identify responses with the same part in the interface\n","args":[],"cases":[["InterfaceWithFutureDiff",["Web.InterfaceWithFutureDiff"]],["InterfaceWithoutFutureDiff",["Web.InterfaceWithoutFutureDiff"]]]},{"name":"InterfaceSingle","comment":" A \"non-batched\" [`Interface`](#Interface).\nTo create one, use the helpers in `Web.Time`, `.Dom`, `.Http` etc.\n","args":["future"],"cases":[["InterfaceWithFuture",["Web.InterfaceSingleWithFuture future"]],["InterfaceWithoutFuture",["Web.InterfaceSingleWithoutFuture"]]]},{"name":"InterfaceSingleListen","comment":" An [`InterfaceSingleWithFuture`](#InterfaceSingleWithFuture) that will possibly notify elm multiple times in the future.\n","args":["future"],"cases":[["WindowEventListen",["{ eventName : String.String, on : Json.Decode.Decoder future }"]],["WindowVisibilityChangeListen",["Web.WindowVisibility -> future"]],["WindowAnimationFrameListen",["Time.Posix -> future"]],["WindowPreferredLanguagesChangeListen",["List.List String.String -> future"]],["DocumentEventListen",["{ eventName : String.String, on : Json.Decode.Decoder future }"]],["TimePeriodicallyListen",["{ intervalDurationMilliSeconds : Basics.Int, on : Time.Posix -> future }"]],["SocketMessageListen",["{ id : Web.SocketId, on : String.String -> future }"]],["LocalStorageRemoveOnADifferentTabListen",["{ key : String.String, on : AppUrl.AppUrl -> future }"]],["LocalStorageSetOnADifferentTabListen",["{ key : String.String, on : { appUrl : AppUrl.AppUrl, oldValue : Maybe.Maybe String.String, newValue : String.String } -> future }"]],["GeoLocationChangeListen",["Web.GeoLocation -> future"]],["GamepadsChangeListen",["Dict.Dict Basics.Int Web.Gamepad -> future"]]]},{"name":"InterfaceSingleListenId","comment":" Safe to ignore. Possible identifier for an interface single that can send back values to elm\nat multiple times in the future\n","args":[],"cases":[["IdWindowEventListen",["String.String"]],["IdWindowVisibilityChangeListen",[]],["IdWindowAnimationFrameListen",[]],["IdWindowPreferredLanguagesChangeListen",[]],["IdDocumentEventListen",["String.String"]],["IdTimePeriodicallyListen",["{ milliSeconds : Basics.Int }"]],["IdSocketMessageListen",["Web.SocketId"]],["IdLocalStorageRemoveOnADifferentTabListen",["{ key : String.String }"]],["IdLocalStorageSetOnADifferentTabListen",["{ key : String.String }"]],["IdGeoLocationChangeListen",[]],["IdGamepadsChangeListen",[]]]},{"name":"InterfaceSingleRequest","comment":" An [`InterfaceSingleWithFuture`](#InterfaceSingleWithFuture) that will elm only once in the future.\n","args":["future"],"cases":[["TimePosixRequest",["Time.Posix -> future"]],["TimezoneOffsetRequest",["Basics.Int -> future"]],["TimezoneNameRequest",["Time.ZoneName -> future"]],["RandomUnsignedInt32sRequest",["{ count : Basics.Int, on : List.List Basics.Int -> future }"]],["WindowSizeRequest",["{ width : Basics.Int, height : Basics.Int } -> future"]],["WindowPreferredLanguagesRequest",["List.List String.String -> future"]],["NavigationUrlRequest",["AppUrl.AppUrl -> future"]],["HttpRequest",["Web.HttpRequest future"]],["ClipboardRequest",["String.String -> future"]],["LocalStorageRequest",["{ key : String.String, on : Maybe.Maybe String.String -> future }"]],["GeoLocationRequest",["Web.GeoLocation -> future"]],["GamepadsRequest",["Dict.Dict Basics.Int Web.Gamepad -> future"]]]},{"name":"InterfaceSingleRequestId","comment":" Safe to ignore. Possible identifier for an interface single that can send back values to elm\nonly once in the future\n","args":[],"cases":[["IdTimePosixRequest",[]],["IdTimezoneOffsetRequest",[]],["IdTimezoneNameRequest",[]],["IdRandomUnsignedInt32sRequest",["Basics.Int"]],["IdWindowSizeRequest",[]],["IdWindowPreferredLanguagesRequest",[]],["IdNavigationUrlRequest",[]],["IdHttpRequest",["Web.HttpRequestId"]],["IdClipboardRequest",[]],["IdLocalStorageRequest",["{ key : String.String }"]],["IdGeoLocationRequest",[]],["IdGamepadsRequest",[]]]},{"name":"InterfaceSingleWithFuture","comment":" An [`InterfaceSingle`](#InterfaceSingle) that will notify elm some time in the future.\n","args":["future"],"cases":[["DomNodeRender",["Web.DomNode future"]],["AudioSourceLoad",["{ url : String.String, on : Result.Result Web.AudioSourceLoadError Web.AudioSource -> future }"]],["SocketConnect",["{ address : String.String, on : Web.SocketConnectionEvent -> future }"]],["NotificationShow",["{ id : String.String, message : String.String, details : String.String, on : Web.NotificationClicked -> future }"]],["Request",["Web.InterfaceSingleRequest future"]],["Listen",["Web.InterfaceSingleListen future"]]]},{"name":"InterfaceSingleWithoutFuture","comment":" An [`InterfaceSingle`](#InterfaceSingle) that will never notify elm\n","args":[],"cases":[["DocumentTitleReplaceBy",["String.String"]],["DocumentAuthorSet",["String.String"]],["DocumentKeywordsSet",["List.List String.String"]],["DocumentDescriptionSet",["String.String"]],["ConsoleLog",["String.String"]],["ConsoleWarn",["String.String"]],["ConsoleError",["String.String"]],["NavigationReplaceUrl",["AppUrl.AppUrl"]],["NavigationPushUrl",["AppUrl.AppUrl"]],["NavigationGo",["Basics.Int"]],["NavigationLoad",["String.String"]],["NavigationReload",[]],["FileDownloadUnsignedInt8s",["{ mimeType : String.String, name : String.String, content : List.List Basics.Int }"]],["ClipboardReplaceBy",["String.String"]],["AudioPlay",["Web.Audio"]],["SocketMessage",["{ id : Web.SocketId, data : String.String }"]],["SocketDisconnect",["Web.SocketId"]],["LocalStorageSet",["{ key : String.String, value : Maybe.Maybe String.String }"]],["NotificationAskForPermission",[]]]},{"name":"InterfaceWithFutureDiff","comment":" Actions that will notify elm some time in the future\n","args":[],"cases":[["EditDom",["Web.EditDomDiff"]],["AddSocketConnect",["{ address : String.String }"]],["AddAudioSourceLoad",["String.String"]],["AddNotificationShow",["{ id : String.String, message : String.String, details : String.String }"]],["AddRequest",["Web.InterfaceSingleRequestId"]],["AddListen",["Web.InterfaceSingleListenId"]]]},{"name":"InterfaceWithoutFutureDiff","comment":" Actions that will never notify elm again\n","args":[],"cases":[["Add",["Web.InterfaceSingleWithoutFuture"]],["EditAudio",["{ url : String.String, startTime : Time.Posix, replacement : Web.EditAudioDiff }"]],["RemoveHttpRequest",["Web.HttpRequestId"]],["RemoveDom",[]],["RemoveSocketConnect",["{ address : String.String }"]],["RemoveAudio",["{ url : String.String, startTime : Time.Posix }"]],["EditNotification",["{ id : String.String, message : String.String, details : String.String }"]],["RemoveNotificationShow",["{ message : String.String, details : String.String }"]],["RemoveListen",["Web.InterfaceSingleListenId"]]]},{"name":"NotificationClicked","comment":" The user clicked a displayed notification,\nmoving the focus to our page\n","args":[],"cases":[["NotificationClicked",[]]]},{"name":"ProgramEvent","comment":" Ignore the specific variants, this is just exposed so can\nfor example simulate it more easily in tests, add a debugger etc.\n\nA [`Web.program`](#program) would have this type\n\n main : Platform.Program () (Web.State YourState) (Web.Event YourState)\n main =\n Web.toProgram ...\n\nIn practice, please use [`Web.Program YourState`](#Program)\n\n","args":["appState"],"cases":[["InterfaceDiffFailedToDecode",["Json.Decode.Error"]],["InterfaceEventDataFailedToDecode",["Json.Decode.Error"]],["InterfaceEventIgnored",[]],["AppEventToNewAppState",["appState"]]]},{"name":"ProgramState","comment":" Ignore the specific fields, this is just exposed so can\nfor example simulate it more easily in tests, add a debugger etc.\n\nA [`Web.program`](#program) would have this type\n\n main : Platform.Program () (Web.State YourState) (Web.Event YourState)\n main =\n Web.toProgram ...\n\nIn practice, please use [`Web.Program YourState`](#Program)\n\n","args":["appState"],"cases":[["State",["{ interface : FastDict.Dict (List.List String.String) (Web.InterfaceSingle appState), appState : appState }"]]]},{"name":"ReplacementInEditDomDiff","comment":" What parts of a node are replaced. Either all modifiers of a certain kind or the whole node\n","args":[],"cases":[["ReplacementDomNode",["Web.DomNodeId"]],["ReplacementDomElementStyles",["Dict.Dict String.String String.String"]],["ReplacementDomElementAttributes",["Dict.Dict String.String String.String"]],["ReplacementDomElementAttributesNamespaced",["Dict.Dict ( String.String, String.String ) String.String"]],["ReplacementDomElementScrollToPosition",["Maybe.Maybe { fromLeft : Basics.Float, fromTop : Basics.Float }"]],["ReplacementDomElementScrollToShow",["Maybe.Maybe { x : Web.DomElementVisibilityAlignment, y : Web.DomElementVisibilityAlignment }"]],["ReplacementDomElementScrollPositionRequest",[]],["ReplacementDomElementEventListens",["Dict.Dict String.String Web.DefaultActionHandling"]]]},{"name":"SocketConnectionEvent","comment":" An indication that connection has changed\nafter having initiated [`Web.Socket.connectTo`](Web-Socket#connectTo).\n\n - `SocketConnected`: connection has been opened. Gives access to a [`Web.SocketId`](#SocketId)\n - `SocketDisconnected`: connection has been closed with\n - the close `code` sent by the server\n - The `reason` indicating why the server closed the connection, specific to the particular server and sub-protocol\n\n","args":[],"cases":[["SocketConnected",["Web.SocketId"]],["SocketDisconnected",["{ code : Basics.Int, reason : String.String }"]]]},{"name":"SocketId","comment":" Identifier for a [`Web.Socket`](Web-Socket) that can be used to [communicate](Web-Socket#communicate)\n","args":[],"cases":[["SocketId",["Basics.Int"]]]},{"name":"WindowVisibility","comment":" The visibility to the user\n\n - `WindowHidden`: the user has navigated to a new page, switched tabs, closed the tab, minimized or closed the browser, or, on mobile, switched from the browser to a different app\n - `WindowShown` otherwise\n\n","args":[],"cases":[["WindowShown",[]],["WindowHidden",[]]]}],"aliases":[{"name":"Audio","comment":" Some kind of sound we want to play. To create `Audio`, start with [`Web.Audio.fromSource`](Web-Audio#fromSource)\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { url : String.String, startTime : Time.Posix, volume : Web.AudioParameterTimeline, speed : Web.AudioParameterTimeline, stereoPan : Web.AudioParameterTimeline, processingLastToFirst : List.List Web.AudioProcessing }"},{"name":"AudioParameterTimeline","comment":" defining how loud a sound should be at any point in time\n","args":[],"type":"{ startValue : Basics.Float, keyFrames : List.List { time : Time.Posix, value : Basics.Float } }"},{"name":"AudioSource","comment":" Audio data we can use to play sounds.\nUse [`Web.Audio.sourceLoad`](Web-Audio#sourceLoad) to fetch an [`AudioSource`](#AudioSource).\n\nYou can also use the contained source `duration`, for example to find fade-out times or to create a loop:\n\n audioLoop : AudioSource -> Time.Posix -> Time.Posix -> Audio\n audioLoop source initialTime lastTick =\n Web.Audio.fromSource source\n (Duration.addTo\n initialTime\n (source.duration\n |> Quantity.multiplyBy\n (((Duration.from initialTime lastTick |> Duration.inSeconds)\n / (source.duration |> Duration.inSeconds)\n )\n |> floor\n |> toFloat\n )\n )\n )\n\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { url : String.String, duration : Duration.Duration }"},{"name":"DomElement","comment":" A tagged DOM node that can itself contain child [node](#DomNode)s\n","args":["future"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { namespace : Maybe.Maybe String.String, tag : String.String, styles : Dict.Dict String.String String.String, attributes : Dict.Dict String.String String.String, attributesNamespaced : Dict.Dict ( String.String, String.String ) String.String, scrollToPosition : Maybe.Maybe { fromLeft : Basics.Float, fromTop : Basics.Float }, scrollToShow : Maybe.Maybe { x : Web.DomElementVisibilityAlignment, y : Web.DomElementVisibilityAlignment }, scrollPositionRequest : Maybe.Maybe ({ fromLeft : Basics.Float, fromTop : Basics.Float } -> future), eventListens : Dict.Dict String.String { on : Json.Decode.Value -> future, defaultActionHandling : Web.DefaultActionHandling }, subs : Array.Array (Web.DomNode future) }"},{"name":"DomElementId","comment":" Safe to ignore. Identifier for a [`DomElement`](#DomElement)\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { namespace : Maybe.Maybe String.String, tag : String.String, styles : Dict.Dict String.String String.String, attributes : Dict.Dict String.String String.String, attributesNamespaced : Dict.Dict ( String.String, String.String ) String.String, scrollToPosition : Maybe.Maybe { fromLeft : Basics.Float, fromTop : Basics.Float }, scrollToShow : Maybe.Maybe { x : Web.DomElementVisibilityAlignment, y : Web.DomElementVisibilityAlignment }, scrollPositionRequest : Basics.Bool, eventListens : Dict.Dict String.String Web.DefaultActionHandling, subs : Array.Array Web.DomNodeId }"},{"name":"EditDomDiff","comment":" Change the current node at a given path using a given [`ReplacementInEditDomDiff`](#ReplacementInEditDomDiff)\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { path : List.List Basics.Int, replacement : Web.ReplacementInEditDomDiff }"},{"name":"Gamepad","comment":" Controller information on button presses, thumbstick positions etc.\n\n - `primaryButton`: The most common action like \"enter\"/\"confirm\" or jump\n\n - `secondaryButton`: Usually \"cancel\"/\"skip\" or a common ability like duck/sneak, drop or heal\n\n - `tertiaryButton`: common-ish ability like consume, interact, reload or an ultimate power\n\n - `quaternaryButton`: less common action like quick menu or mode switch\n\n - `leftBumperButton`, `rightBumperButton`: The top row of smaller buttons on the side opposite of you, sometimes called shoulder buttons.\n Often used for alternative menu actions like slot switching or quick map\n\n - `leftTriggerButton`, `rightTriggerButton`: The bottom row of larger buttons on the side opposite of you.\n Often used for holdable abilities like sliding or dashing\n\n - `selectButton`: Usually opens an in-world menu with for example inventory, lore, ability overview or a map\n\n - `startButton`: Usually pauses the game and opens a menu with options like settings and quit\n\n - `leftThumbstickButton`, `rightThumbstickButton`: Not all gamepads have these, so they often either double existing actions like \"confirm\"\n or perform actions that are only very rarely helpful, like hiding ui elements or making a screenshot\n\n - `upButton`, `downBottom`, `leftButton`, `rightButton`: exactly one step in a direction, usually in a (quick) menu/inventory\n\n - \\`homeButton: Usually turns the gamepad on/off, or changes the state of the game\n\n - `touchpadButton`: Not present on most gamepads. While the touchpad is often used for controlling the mouse, it can also be used as a simple button\n\n - `thumbstickLeft`, `thumbstickRight`: Those wiggly that can be moved in any direction by any amount.\n They are provided as `x, y` signed percentages\n\n - `kindId`: some information about the gamepad, usually containing the USB vendor, product id of the gamepad\n and the name of the gamepad as provided by the driver. See [mdn](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/id)\n\n You can use this information to for example determine how to show controls\n\n - `buttonsAdditional`, `thumbsticksAdditional`: Maybe you have a weird gamepad with 3 thumbsticks? These might help 🤷\n\nImplementation note:\nAs you know, gamepad layouts differ between models.\nFor most of them, we're able to map them to the buttons and thumbsticks above.\nIf you experience issues with some model, [open an issue]()\n\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { primaryButton : Web.GamepadButton, secondaryButton : Web.GamepadButton, tertiaryButton : Web.GamepadButton, quaternaryButton : Web.GamepadButton, leftBumperButton : Web.GamepadButton, rightBumperButton : Web.GamepadButton, leftTriggerButton : Web.GamepadButton, rightTriggerButton : Web.GamepadButton, selectButton : Web.GamepadButton, startButton : Web.GamepadButton, leftThumbstickButton : Web.GamepadButton, rightThumbstickButton : Web.GamepadButton, upButton : Web.GamepadButton, downButton : Web.GamepadButton, leftButton : Web.GamepadButton, rightButton : Web.GamepadButton, homeButton : Web.GamepadButton, touchpadButton : Web.GamepadButton, additionalButtons : List.List Web.GamepadButton, kindId : String.String, thumbstickLeft : { x : Basics.Float, y : Basics.Float }, thumbstickRight : { x : Basics.Float, y : Basics.Float }, thumbsticksAdditional : List.List { x : Basics.Float, y : Basics.Float } }"},{"name":"GeoLocation","comment":" Position and (if available) altitude of the device on Earth, as well as the accuracy with which these properties are calculated.\nThe geographic position information is provided in terms of World Geodetic System coordinates (WGS84).\n\nDevice movement direction and speed might also be provided.\n\n[`Length`](https://dark.elm.dmy.fr/packages/ianmackenzie/elm-units/latest/Length),\n[`Angle`](https://dark.elm.dmy.fr/packages/ianmackenzie/elm-units/latest/Angle) and\n[`Speed`](https://dark.elm.dmy.fr/packages/ianmackenzie/elm-units/latest/Speed)\nare from `ianmackenzie/elm-units`\n\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { latitudeInDecimalDegrees : Basics.Float, longitudeInDecimalDegrees : Basics.Float, latitudeLongitudeAccuracy : Maybe.Maybe Length.Length, altitudeAboveNominalSeaLevel : Maybe.Maybe Length.Length, altitudeAccuracy : Maybe.Maybe Length.Length, headingWith0AsTrueNorthAndIncreasingClockwise : Maybe.Maybe Angle.Angle, speed : Maybe.Maybe Speed.Speed }"},{"name":"HttpMetadata","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\nNote: 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 dictionary.\nThe values are separated by commas, following the rules outlined [here](https://stackoverflow.com/questions/4371328/are-duplicate-http-response-headers-acceptable).\n\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { url : String.String, statusCode : Basics.Int, statusText : String.String, headers : Dict.Dict String.String String.String }"},{"name":"HttpRequest","comment":" An HTTP request for use in an [`Interface`](#Interface).\n\nYou can set custom headers as needed.\nThe `timeout` can be set to a number of milliseconds you are willing to wait before giving up\n\n","args":["future"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { url : String.String, method : String.String, headers : List.List { name : String.String, value : String.String }, body : Web.HttpBody, expect : Web.HttpExpect future, timeout : Maybe.Maybe Basics.Int }"},{"name":"HttpRequestId","comment":" Safe to ignore. Identifier for an [`HttpRequest`](#HttpRequest)\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { url : String.String, method : String.String, headers : List.List { name : String.String, value : String.String }, body : Web.HttpBody, expect : Web.HttpExpectId, timeout : Maybe.Maybe Basics.Int }"},{"name":"Interface","comment":" Incoming and outgoing effects.\nTo create one, use the helpers in [`Web.Time`](Web-Time), [`Web.Dom`](Web-Dom), [`Web.Http`](Web-Http) etc.\n\nTo combine multiple, use [`Web.interfaceBatch`](#interfaceBatch) and [`Web.interfaceNone`](#interfaceNone)\n\n","args":["future"],"type":"Rope.Rope (Web.InterfaceSingle future)"},{"name":"Program","comment":" A [`Platform.Program`](https://dark.elm.dmy.fr/packages/elm/core/latest/Platform#Program)\nthat elm can run,\nproduced by [`Web.program`](#program)\n","args":["state"],"type":"Platform.Program () (Web.ProgramState state) (Web.ProgramEvent state)"},{"name":"ProgramConfig","comment":" What's needed to create a state-interface program.\n\n - the state is everything the program knows (what The Elm Architecture calls model)\n\n - The [`Interface`](#Interface) is the face to the outside world and can be created using the helpers in [`Web.Dom`](Web-Dom), [`Web.Time`](Web-Time), [`Web.Http`](Web-Http) etc.\n\n - connections to and from js\n\n port toJs : Json.Encode.Value -> Cmd event_\n\n port fromJs : (Json.Encode.Value -> event) -> Sub event\n\n","args":["state"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { initialState : state, interface : state -> Web.Interface state, ports : { toJs : Json.Encode.Value -> Platform.Cmd.Cmd Basics.Never, fromJs : (Json.Encode.Value -> Web.ProgramEvent state) -> Platform.Sub.Sub (Web.ProgramEvent state) } }"}],"values":[{"name":"findInterfaceAssociatedWithDiffComingBack","comment":" Quickly find out what [interface](#InterfaceSingleWithFuture) a given\n[diff](#InterfaceWithFutureDiff) that comes back belonged to.\n\nUse in combination with [`interfaceFutureJsonDecoder`](#interfaceFutureJsonDecoder) to feed it the event data json that comes back\n\n","type":"Web.InterfaceWithFutureDiff -> FastDict.Dict (List.List String.String) (Web.InterfaceSingle future) -> Maybe.Maybe (Web.InterfaceSingleWithFuture future)"},{"name":"interfaceBatch","comment":" Combine multiple [`Interface`](#Interface)s into one.\n","type":"List.List (Web.Interface future) -> Web.Interface future"},{"name":"interfaceDiffs","comment":" Determine which outgoing effects need to be executed based on the difference between old and updated interfaces\n\nTo for example determine the initial effects, use\n\n { old = Set.StructuredId.empty, updated = initialInterface }\n |> interfaceDiffs\n\n","type":"{ old : FastDict.Dict (List.List String.String) (Web.InterfaceSingle future), updated : FastDict.Dict (List.List String.String) (Web.InterfaceSingle future) } -> List.List Web.InterfaceDiff"},{"name":"interfaceFutureJsonDecoder","comment":" [json `Decoder`](https://dark.elm.dmy.fr/packages/elm/json/latest/Json-Decode#Decoder)\nfor the transformed event data coming back\n","type":"Web.InterfaceSingleWithFuture future -> Json.Decode.Decoder future"},{"name":"interfaceFutureMap","comment":" Take what the [`Interface`](#Interface) can come back with and return a different future value.\n\nIn practice, this is sometimes used like a kind of event-config pattern:\n\n Web.Time.posixRequest\n |> Web.interfaceFutureMap (\\timeNow -> TimeReceived timeNow)\n\n button \"show all entries\"\n |> Web.Dom.render\n |> Web.interfaceFutureMap (\\Pressed -> ShowAllEntriesButtonClicked)\n\nsometimes as a way to deal with all events (like `update` in The Elm Architecture)\n\n ...\n |> Web.interfaceFutureMap\n (\\event ->\n case event of\n MouseMovedTo newMousePoint ->\n { state | mousePoint = newMousePoint }\n\n CounterDecreaseClicked ->\n { state | counter = state.counter - 1 }\n\n CounterIncreaseClicked ->\n { state | counter = state.counter + 1 }\n )\n\nand sometimes to nest events (like `Cmd.map/Task.map/Sub.map/...` in The Elm Architecture):\n\n type Event\n = DirectoryTreeViewEvent TreeUiEvent\n | SortButtonClicked\n\n type TreeUiEvent\n = Expanded TreePath\n | Collapsed TreePath\n\n interface : State -> Interface State\n interface state =\n ...\n [ treeUi ..\n |> Web.interfaceFutureMap DirectoryTreeViewEvent\n , ...\n ]\n |> Web.Dom.render\n\n treeUi : ... -> Web.DomNode TreeUiEvent\n\nIn all these examples, you end up converting the narrow future representation of part of the interface\nto a broader representation for the parent interface\n\n","type":"(future -> mappedFuture) -> Web.Interface future -> Web.Interface mappedFuture"},{"name":"interfaceNone","comment":" Doing nothing as an [`Interface`](#Interface). These two examples are equivalent:\n\n Web.interfaceBatch [ a, Web.interfaceNone, b ]\n\nand\n\n Web.interfaceBatch\n (List.filterMap identity\n [ a |> Just, Nothing, b |> Just ]\n )\n\n","type":"Web.Interface future_"},{"name":"program","comment":" Create an elm [`Program`](https://dark.elm.dmy.fr/packages/elm/core/latest/Platform#Program)\nwith a given [`Web.ProgramConfig`](#ProgramConfig).\n","type":"Web.ProgramConfig state -> Web.Program state"},{"name":"programInit","comment":" The \"init\" part for an embedded program\n","type":"Web.ProgramConfig state -> ( Web.ProgramState state, Platform.Cmd.Cmd (Web.ProgramEvent state) )"},{"name":"programSubscriptions","comment":" The \"subscriptions\" part for an embedded program\n","type":"Web.ProgramConfig state -> Web.ProgramState state -> Platform.Sub.Sub (Web.ProgramEvent state)"},{"name":"programUpdate","comment":" The \"update\" part for an embedded program\n","type":"Web.ProgramConfig state -> Web.ProgramEvent state -> Web.ProgramState state -> ( Web.ProgramState state, Platform.Cmd.Cmd (Web.ProgramEvent state) )"}],"binops":[]},{"name":"Web.Audio","comment":" Play [`Audio`](Web#Audio) as part of an [`Interface`](Web#Interface).\n\n import Time\n import Web\n import Web.Audio\n\n type alias State =\n { musicSource : Maybe (Result Web.AudioSourceLoadError Audio.Source)\n , musicStartTime : Time.Posix\n , soundSetting : SoundSetting\n }\n\n type SoundSetting\n = SoundOn\n | SoundOff\n\n { initialState =\n { musicSource = Nothing\n , soundSetting = SoundOn\n , musicStartTime = Time.millisToPosix 0\n }\n , interface =\n \\state ->\n case state.musicSource of\n Just (Ok musicSource) ->\n case state.soundSetting of\n SoundOff ->\n Web.interfaceNone\n\n SoundOn ->\n Web.Audio.fromSource musicSource model.musicStartTime\n |> Web.Audio.play\n\n _ ->\n Web.Audio.sourceLoad \"https://archive.org/details/lp_the-caretakers-original-motion-picture-sco_elmer-bernstein/disc1/01.03.+Take+Care.mp3\"\n |> Web.interfaceFutureMap\n (\\result -> { state | musicSource = result |> Just })\n }\n\n@docs sourceLoad, fromSource, play\n@docs volumeScaleBy, speedScaleBy, stereoPan\n@docs addLinearConvolutionWith, addHighpassFromFrequency, addLowpassUntilFrequency\n\nTo detune, use [`speedScaleBy`](#speedScaleBy). It's documentation also shows which scale relates to which semitone pitch.\n\n","unions":[],"aliases":[],"values":[{"name":"addHighpassFromFrequency","comment":" Frequencies below a given cutoff [parameter](Web#AudioParameterTimeline) are attenuated;\nfrequencies above it pass through.\n\nHas a 12dB/octave rolloff and no peak at the cutoff.\n\n","type":"Web.AudioParameterTimeline -> Web.Audio -> Web.Audio"},{"name":"addLinearConvolutionWith","comment":" Usually used to apply reverb and or echo.\nGiven a loaded [`AudioSource`](Web#AudioSource) containing the impulse response,\nit performs a [Convolution](https://en.wikipedia.org/wiki/Convolution) with the [`Audio`](Web#Audio)\n\nIf you need some nice impulse wavs to try it out, there's a few at [`dhiogoboza/audio-convolution`](https://github.com/dhiogoboza/audio-convolution/tree/master/impulses).\nIf you know more nice ones, don't hesitate to open an issue or a PR.\n\n","type":"Web.AudioSource -> Web.Audio -> Web.Audio"},{"name":"addLowpassUntilFrequency","comment":" Frequencies below a given cutoff [parameter](Web#AudioParameterTimeline) pass through;\nfrequencies above it are attenuated.\n\nHas a 12dB/octave rolloff and no peak at the cutoff.\n\n","type":"Web.AudioParameterTimeline -> Web.Audio -> Web.Audio"},{"name":"fromSource","comment":" Create [`Audio`](Web#Audio) from an given loaded [source](Web#AudioSource)\nwhich will play at a given [time](https://dark.elm.dmy.fr/packages/elm/time/latest/)\n\n -- play a song at half speed and wait 2 seconds after the usual song start time before starting\n Web.Audio.fromSource\n myCoolSong\n (Duration.addTo usualSongStartTime (Duration.seconds 2))\n |> Web.Audio.speedScaleBy (Web.Audio.Parameter.at 0.5)\n\nNote that in some browsers audio will be muted until the user interacts with the webpage.\n\n","type":"Web.AudioSource -> Time.Posix -> Web.Audio"},{"name":"play","comment":" An [`Interface`](Web#Interface) for playing [`Audio`](Web#Audio) created with [`fromSource`](#fromSource).\n\nTo play multiple audios:\n\n [ audio0, audio1, audio2 ]\n |> List.map Web.Audio.play\n |> Web.interfaceBatch\n\n","type":"Web.Audio -> Web.Interface future_"},{"name":"sourceLoad","comment":" An [`Interface`](Web#Interface) for fetching audio data from a given url\nand returning an [`AudioSource`](Web#AudioSource) to use with [`fromSource`](#fromSource).\n","type":"String.String -> Web.Interface (Result.Result Web.AudioSourceLoadError Web.AudioSource)"},{"name":"speedScaleBy","comment":" Scale the playback rate by a given factor. This will also affect pitch.\n\nFor example, `Web.Audio.speedScaleBy 0.5` means playback will take twice as long and the pitch will be one octave lower, see [AudioBufferSourceNode.playbackRate](https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/playbackRate)\n\nIn general, to pitch by semitones:\n\n Web.Audio.speedScaleBy (2 ^ (semitones / 12))\n\nNote: It would be possible to modify the signal to compensate for the pitch change,\nsee [Audio time stretching and pitch scaling](https://en.wikipedia.org/wiki/Audio_time_stretching_and_pitch_scaling).\nHelp appreciated!\n\n","type":"Web.AudioParameterTimeline -> Web.Audio -> Web.Audio"},{"name":"stereoPan","comment":" Change the stereo panning with a given a signed percentage [parameter](Web#AudioParameterTimeline).\n\nFor example `Web.Audio.pan -0.9` means that the sound is almost fully balanced towards the left speaker\n\n","type":"Web.AudioParameterTimeline -> Web.Audio -> Web.Audio"},{"name":"volumeScaleBy","comment":" Scale how loud it is.\n1 preserves the current volume, 0.5 halves it, and 0 mutes it.\nIf the the volume is less than 0, 0 will be used instead.\n","type":"Web.AudioParameterTimeline -> Web.Audio -> Web.Audio"}],"binops":[]},{"name":"Web.Audio.Parameter","comment":" Build an [`AudioParameterTimeline`](Web#AudioParameterTimeline)\n\n@docs at, through\n\n","unions":[],"aliases":[],"values":[{"name":"at","comment":" Set it to a constant value. Add [`through`](#through) to make it transition from this starting value over time.\n","type":"Basics.Float -> Web.AudioParameterTimeline"},{"name":"through","comment":" Specify a key value at a given absolute point in time.\nThe parameter will then transition linearly between those points.\n\nLet's define an audio function that fades in to 1 and then fades out until it's 0 again.\n\n import Duration\n import Time\n import Web.Audio.Parameter\n\n\n -- 1 ________\n -- / \\\n -- 0 ____________/ \\_______\n -- t -> fade in fade out\n fadeInOut fadeInStartTime fadeOutEndTime audio =\n Web.Audio.Parameter.at 0\n |> Web.Audio.Parameter.through fadeInStartTime 1\n |> Web.Audio.Parameter.through (Duration.addTo fadeInStartTime Duration.second) 1\n |> Web.Audio.Parameter.through (Duration.subtractFrom fadeOutEndTime Duration.second) 1\n |> Web.Audio.Parameter.through fadeOutEndTime 0\n\n - 🧩 `Duration` is from [ianmackenzie/elm-units](https://dark.elm.dmy.fr/packages/ianmackenzie/elm-units/latest/)\n - 🧩 `Time` is from [elm/time](https://dark.elm.dmy.fr/packages/elm/time/latest/)\n\nYou do not have to worry about order.\n\n","type":"Time.Posix -> Basics.Float -> Web.AudioParameterTimeline -> Web.AudioParameterTimeline"}],"binops":[]},{"name":"Web.Clipboard","comment":" Helpers for clipboard interactions as part of an [`Interface`](Web#Interface)\n\n@docs request, replaceBy\n\nNote: To listen for [copy, cut and paste events](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent),\nuse [`Web.Dom.listenTo`](Web-Dom#listenTo)\n\n","unions":[],"aliases":[],"values":[{"name":"replaceBy","comment":" An [`Interface`](Web#Interface) for setting the textual contents of the system clipboard.\n\nNote: uses [`navigator.clipboard.writeText`](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText)\n\n","type":"String.String -> Web.Interface future_"},{"name":"request","comment":" An [`Interface`](Web#Interface) for reading the textual contents of the system clipboard.\n\nNote: uses [`navigator.clipboard.readText`](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText)\n\n","type":"Web.Interface String.String"}],"binops":[]},{"name":"Web.Console","comment":" Helpers for console interactions as part of an [`Interface`](Web#Interface)\n\n@docs log, warn, error\n\n","unions":[],"aliases":[],"values":[{"name":"error","comment":" An [`Interface`](Web#Interface) for printing a message that something failed with bad consequences, for example\n\n> ❌ decoding the selected file failed. Please report this bug at ...\n\nNote: uses [`console.error`](https://developer.mozilla.org/en-US/docs/Web/API/console/error_static)\n\n","type":"String.String -> Web.Interface future_"},{"name":"log","comment":" An [`Interface`](Web#Interface) for printing a message with general information\nlike if certain tasks have been successful\n\n> survey submitted and received successfully\n\nDepending on what minifying tools you use for your production build, these might get removed.\n\nNote: uses [`console.log`](https://developer.mozilla.org/en-US/docs/Web/API/console/log_static),\njust like [`Debug.log`](https://dark.elm.dmy.fr/packages/elm/core/latest/Debug#log)\n\n","type":"String.String -> Web.Interface future_"},{"name":"warn","comment":" An [`Interface`](Web#Interface) for printing a message that something didn't succeed but you could recover from, for example\n\n> ⚠️ Unknown device - there may be compatibility issues.\n\n> ⚠️ Recoverable upload failure, will retry. Error was: no status.\n\nNote: uses [`console.warn`](https://developer.mozilla.org/en-US/docs/Web/API/console/warn_static)\n\n","type":"String.String -> Web.Interface future_"}],"binops":[]},{"name":"Web.Dom","comment":" Helpers for [DOM node types](Web#DomNode) as part of an [`Interface`](Web#Interface).\n\nThese are primitives used for svg and html.\nCompare with [`elm/virtual-dom`](https://dark.elm.dmy.fr/packages/elm/virtual-dom/latest/)\n\n@docs text\n@docs element, elementNamespaced\n@docs Modifier, ModifierSingle, attribute, attributeNamespaced, style\n@docs listenTo, listenToPreventingDefaultAction\n@docs scrollToShow, scrollPositionRequest, scrollToPosition\n@docs modifierFutureMap, modifierBatch, modifierNone\n@docs futureMap, render\n\n","unions":[{"name":"ModifierSingle","comment":" An individual [`Modifier`](#Modifier).\nCreate using [`attribute`](#attribute), [`style`](#style), [`listenTo`](#listenTo).\n","args":["future"],"cases":[["Attribute",["{ namespace : Maybe.Maybe String.String, key : String.String, value : String.String }"]],["Style",["{ key : String.String, value : String.String }"]],["ScrollToPosition",["{ fromLeft : Basics.Float, fromTop : Basics.Float }"]],["ScrollToShow",["{ x : Web.DomElementVisibilityAlignment, y : Web.DomElementVisibilityAlignment }"]],["ScrollPositionRequest",["{ fromLeft : Basics.Float, fromTop : Basics.Float } -> future"]],["Listen",["{ eventName : String.String, on : Json.Decode.Value -> future, defaultActionHandling : Web.DefaultActionHandling }"]]]}],"aliases":[{"name":"Modifier","comment":" Set the behavior of a [`Web.Dom.element`](Web-Dom#element).\nTo create one, use [`attribute`](#attribute), [`style`](#style), [`listenTo`](#listenTo).\nTo combine multiple, use [`Web.Dom.modifierBatch`](#modifierBatch) and [`Web.Dom.modifierNone`](#modifierNone)\n\nFor example to get `elm`\n\n Web.Dom.element \"a\"\n [ Web.Dom.attribute \"href\" \"https://elm-lang.org\" ]\n [ Web.Dom.text \"elm\" ]\n\nBtw: If you can think of a nicer name for this like \"customization\", \"characteristic\" or \"aspect\",\nplease [open an issue](https://github.com/lue-bird/elm-state-interface/issues/new)!\n\n","args":["future"],"type":"Rope.Rope (Web.Dom.ModifierSingle future)"}],"values":[{"name":"attribute","comment":" A key-value attribute [`Modifier`](#Modifier)\n","type":"String.String -> String.String -> Web.Dom.Modifier future_"},{"name":"attributeNamespaced","comment":" A namespaced key-value attribute [`Modifier`](#Modifier).\nFor example, you could define an SVG xlink href attribute as\n\n attributeXlinkHref : String -> Modifier msg\n attributeXlinkHref value =\n Web.Dom.attributeNamespaced \"http://www.w3.org/1999/xlink\" \"xlink:href\" value\n\n","type":"String.String -> String.String -> String.String -> Web.Dom.Modifier future_"},{"name":"element","comment":" Create a DOM element with a given tag, [`Modifier`](#Modifier)s and sub-[node](Web#DomNode)s.\nFor example to get `
flying
`\n\n Web.Dom.element \"p\"\n []\n [ Web.Dom.text \"flying\" ]\n\nTo create SVG elements, use [`Web.Svg.element`](Web-Svg#element)\n\n","type":"String.String -> List.List (Web.Dom.Modifier future) -> List.List (Web.DomNode future) -> Web.DomNode future"},{"name":"elementNamespaced","comment":" Create a DOM element with a given namespace, tag, [`Modifier`](#Modifier)s and sub-[node](Web#DomNode)s.\nFor example, [`Web.Svg`](Web-Svg) defines its elements using\n\n element : String -> List (Modifier future) -> List (DomNode future) -> DomNode future\n element tag modifiers subs =\n Web.Dom.elementNamespaced \"http://www.w3.org/2000/svg\" tag modifiers subs\n\n","type":"String.String -> String.String -> List.List (Web.Dom.Modifier future) -> List.List (Web.DomNode future) -> Web.DomNode future"},{"name":"futureMap","comment":" Wire events from this [`DomNode`](Web#DomNode) to a specific event.\n\n buttonUi \"start\"\n |> Web.Dom.futureMap (\\Clicked -> StartButtonClicked)\n\nwith e.g.\n\n buttonUi : List (Web.DomNode ()) -> Web.DomNode ButtonEvent\n buttonUi subs =\n Web.Dom.element \"button\"\n [ Web.Dom.listenTo \"click\"\n |> Web.Dom.modifierFutureMap (\\_ -> Clicked)\n ]\n [ Web.Dom.text label ]\n\n type ButtonEvent\n = Clicked\n\n","type":"(future -> mappedFuture) -> Web.DomNode future -> Web.DomNode mappedFuture"},{"name":"listenTo","comment":" Listen for a specific DOM event on the [`DomElement`](Web#DomElement).\nUse [`modifierFutureMap`](#modifierFutureMap) to wire this to a specific event.\n\nIf you want to override the browser's default behavior for that event,\nuse [`listenToPreventingDefaultAction`](#listenToPreventingDefaultAction)\n\n","type":"String.String -> Web.Dom.Modifier Json.Decode.Value"},{"name":"listenToPreventingDefaultAction","comment":" Like [`listenTo`](#listenTo) but [preventing the browser's default action](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault).\n\nThat's for example how elm's [`Browser.Events.onSubmit`](https://dark.elm.dmy.fr/packages/elm/html/latest/Html-Events#onSubmit)\nprevents the form from changing the page’s location:\n\n submitListen : Web.Dom.Modifier ()\n submitListen =\n Web.Dom.listenToPreventingDefaultAction \"submit\"\n |> Web.Dom.modifierFutureMap (\\_ -> ())\n\n","type":"String.String -> Web.Dom.Modifier Json.Decode.Value"},{"name":"modifierBatch","comment":" Combine multiple [`Modifier`](#Modifier)s into one.\n","type":"List.List (Web.Dom.Modifier future) -> Web.Dom.Modifier future"},{"name":"modifierFutureMap","comment":" Wire events from this [`Modifier`](#Modifier) to a specific event.\n\n Web.Dom.listen \"click\" |> Web.Dom.modifierFutureMap (\\_ -> ButtonClicked)\n\n","type":"(future -> mappedFuture) -> Web.Dom.Modifier future -> Web.Dom.Modifier mappedFuture"},{"name":"modifierNone","comment":" Doing nothing as a [`Modifier`](#Modifier). These two examples are equivalent:\n\n Web.Dom.modifierBatch\n [ a, Web.Dom.modifierNone, b ]\n\nand\n\n Web.Dom.modifierBatch\n (List.filterMap identity\n [ a |> Just, Nothing, b |> Just ]\n )\n\n","type":"Web.Dom.Modifier future_"},{"name":"render","comment":" An [`Interface`](Web#Interface) for displaying a given [`DomNode`](Web#DomNode).\n","type":"Web.DomNode future -> Web.Interface future"},{"name":"scrollPositionRequest","comment":" Getting the current scroll position from the left and top.\n\nUse in combination with [`scrollToPosition`](#scrollToPosition)\nto implement saving and restoring scroll position even when users had navigated off a URL.\n\n","type":"Web.Dom.Modifier { fromLeft : Basics.Float, fromTop : Basics.Float }"},{"name":"scrollToPosition","comment":" Ensure a given initial scroll position in both directions.\nTo move to the edge in a direction, use [`scrollToShow`](#scrollToShow) instead.\n\nUnlike [`style`](#style)s,\nthis is just an initial configuration\nwhich can be changed by user actions.\nSo adding e.g. `scrollToPosition ...`\nwill scroll once the next render happens\nbut will not prevent users from scrolling away.\n\n","type":"{ fromLeft : Basics.Float, fromTop : Basics.Float } -> Web.Dom.Modifier future_"},{"name":"scrollToShow","comment":" Ensure a given initial [`DomElementVisibilityAlignment`](Web#DomElementVisibilityAlignment)\nin both directions.\n\nUnlike [`style`](#style)s,\nthis is just an initial configuration\nwhich can be changed by user actions.\nSo adding e.g. `scrollToShow { y = Web.DomElementStart, x = Web.DomElementStart }`\nwill scroll to the top left once the next render happens\nbut will not prevent users from scrolling away.\n\nNote: Uses [`Element.scrollIntoView`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView)\n\n","type":"{ x : Web.DomElementVisibilityAlignment, y : Web.DomElementVisibilityAlignment } -> Web.Dom.Modifier future_"},{"name":"style","comment":" A key-value style [`Modifier`](#Modifier)\n","type":"String.String -> String.String -> Web.Dom.Modifier future_"},{"name":"text","comment":" Plain text [`DomNode`](Web#DomNode)\n","type":"String.String -> Web.DomNode future_"}],"binops":[]},{"name":"Web.FileDownload","comment":" Helpers for downloading a dynamically generated file as part of an [`Interface`](Web#Interface).\n\nSecurity note: Browsers require downloads to be initiated by a user event.\nSo rather than allowing malicious sites to put files on your computer however they please,\nthe user has to at least click a button first.\nAs a result, the following interfaces only work when they are triggered by some user event.\n\nNote: There's no equivalent module for file select\nsince you can easily replicate the behavior using an input element with type file or file drop area modifiers,\nsee for example [mpizenberg/elm-file](https://dark.elm.dmy.fr/packages/mpizenberg/elm-file/latest/FileValue#load-files-with-an-input).\n\n@docs bytes\n\n","unions":[],"aliases":[],"values":[{"name":"bytes","comment":" An [`Interface`](Web#Interface) for downloading a given file\nwith [`Bytes`](https://dark.elm.dmy.fr/packages/elm/bytes/latest/) as its content,\na given type and and a given default name.\n\nReplacement for [`File.Download.bytes`](https://dark.elm.dmy.fr/packages/elm/file/latest/File-Download#bytes)\n\n","type":"{ name : String.String, mimeType : String.String, content : Bytes.Bytes } -> Web.Interface future_"}],"binops":[]},{"name":"Web.Gamepads","comment":" Observe connected [gamepads and other game controllers](Web#Gamepad)\n(not including motion sensing, gesture recognition etc.).\n\n import Web.Time\n import Web\n\n interface =\n \\state ->\n [ Web.Time.periodicallyListen (Duration.seconds (1 / 50))\n |> Web.interfaceFutureMap\n ..simulate one tick using gamepad inputs..\n , [ Web.Gamepads.request, Web.Gamepads.changeListen ]\n |> Web.interfaceBatch\n |> Web.interfaceFutureMap (\\gamepads -> { state | gamepads = gamepads })\n ]\n |> Web.interfaceBatch\n\nIf your gamepad isn't showing up in the list,\npress some buttons. On some devices, only certain buttons will wake up the gamepad API (the shapes on PS3 controllers, for instance)\n\n@docs request, changeListen\n\n","unions":[],"aliases":[],"values":[{"name":"changeListen","comment":" An [`Interface`](Web#Interface) for detecting changes to which [gamepads](Web#Gamepad)\nare connected and in which ways buttons and axes are activated.\n\nThe given `Dict` keys uniquely identify each device for the whole session,\nso you can for example check for removed and added gamepads using `Dict.diff`\nor track one host device in the state.\n\nImplementation note:\nThe [web gamepad API](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API) does not offer a listener to detect changes.\nSo instead, we poll every 14ms (a bit more often than 60 times/second)\nwhich is just a bit faster than Chrome's actual fetch rate (fetch rate is not part of the specification).\n\nWe want to avoid missed inputs before your next simulation tick,\nso we just had to guess a good interval number.\n