-
Notifications
You must be signed in to change notification settings - Fork 2
/
docs.json
1 lines (1 loc) · 81.5 KB
/
docs.json
1
[{"name":"Web","comment":" A state-interface program that can run in the browser\n\n@docs 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# interface\n\n@docs Interface, interfaceBatch, interfaceNone, interfaceFutureMap\n\nThat's it. Everything else below is types used in the other modules\nlike [`Web.Time`](Web-Time), [`Web.Dom`](Web-Dom), [`Web.Http`](Web-Http) etc.\nLeave them be and look at those modules :)\n\n\n## DOM\n\nTypes used by [`Web.Dom`](Web-Dom)\n\n@docs DomElementHeader, DomElementVisibilityAlignment, DefaultActionHandling\n\n\n## Audio\n\nTypes used by [`Web.Audio`](Web-Audio)\n\n@docs Audio, AudioSource, AudioSourceLoadError, AudioProcessing, AudioParameterTimeline\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 ProgramConfig, 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\nExposed so can for example simulate it more easily in tests, add a debugger etc.\n\n@docs ProgramState, ProgramEvent, InterfaceSingle, DomTextOrElementHeader\n\nTo simulate diffing of interfaces, use\n\n FastDict.merge\n (\\id toAdd -> ..add toAdd..)\n (\\id old updated -> ..edit (interfaceSingleEdits { old, updated })..)\n (id toRemove -> ..remove toRemove..)\n updatedInterfaces\n oldInterfaces\n ..what you fold into..\n\nsee [`FastDict.merge`](https://dark.elm.dmy.fr/packages/miniBill/elm-fast-dict/latest/FastDict#merge)\n\n@docs interfaceSingleEdits, InterfaceSingleEdit, AudioEdit, DomEdit\n\nIf you need more things like json encoders/decoders, [open an issue](https://github.com/lue-bird/elm-state-interface/issues/new)\n\n","unions":[{"name":"AudioEdit","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":"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\n","args":[],"cases":[["AudioSourceLoadDecodeError",[]],["AudioSourceLoadNetworkError",[]]]},{"name":"DefaultActionHandling","comment":" Setting for a listen [`Web.Dom.Modifier`](Web-Dom#Modifier)\nto keep or overwrite the browser's default action\n","args":[],"cases":[["DefaultActionPrevent",[]],["DefaultActionExecute",[]]]},{"name":"DomEdit","comment":" What parts of a node are replaced. Either all modifiers of a certain kind or the whole node\n","args":[],"cases":[["ReplacementDomNode",["Web.DomTextOrElementHeader ()"]],["ReplacementDomElementStyles",["{ edit : List.List { key : String.String, value : String.String }, remove : List.List String.String }"]],["ReplacementDomElementAttributes",["{ edit : List.List { key : String.String, value : String.String }, remove : List.List String.String }"]],["ReplacementDomElementAttributesNamespaced",["{ edit : List.List { namespace : String.String, key : String.String, value : String.String }, remove : List.List { namespace : String.String, key : String.String } }"]],["ReplacementDomElementStringProperties",["{ edit : List.List { key : String.String, value : String.String }, remove : List.List String.String }"]],["ReplacementDomElementBoolProperties",["{ edit : List.List { key : String.String, value : Basics.Bool }, remove : List.List 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":"DomElementVisibilityAlignment","comment":" What part of the [`Web.Dom.Element`](Web-Dom#Element) 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":"DomTextOrElementHeader","comment":" Plain text or a [`DomElementHeader`](#DomElementHeader) for use in an [`Interface`](#Interface).\n","args":["future"],"cases":[["DomText",["String.String"]],["DomElementHeader",["Web.DomElementHeader future"]]]},{"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 - `NetworkError` means the user turned off their wifi, went in a cave, etc.\n or the server CORS is misconfigured.\n Note: A 404 for example does not constitute a network error\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",[]],["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":"InterfaceSingle","comment":" A \"non-batched\" [`Interface`](#Interface).\nTo create one, use the helpers in [`Web.Time`](Web-Time), [`Web.Dom`](Web-Dom), [`Web.Http`](Web-Http) etc.\n","args":["future"],"cases":[["DocumentTitleReplaceBy",["String.String"]],["DocumentAuthorSet",["String.String"]],["DocumentKeywordsSet",["List.List String.String"]],["DocumentDescriptionSet",["String.String"]],["DocumentEventListen",["{ eventName : String.String, on : Json.Decode.Decoder future }"]],["ConsoleLog",["String.String"]],["ConsoleWarn",["String.String"]],["ConsoleError",["String.String"]],["NavigationReplaceUrl",["AppUrl.AppUrl"]],["NavigationPushUrl",["AppUrl.AppUrl"]],["NavigationGo",["Basics.Int"]],["NavigationLoad",["String.String"]],["NavigationReload",[]],["NavigationUrlRequest",["AppUrl.AppUrl -> future"]],["FileDownloadUnsignedInt8s",["{ mimeType : String.String, name : String.String, content : List.List Basics.Int }"]],["ClipboardReplaceBy",["String.String"]],["ClipboardRequest",["String.String -> future"]],["AudioSourceLoad",["{ url : String.String, on : Result.Result Web.AudioSourceLoadError Web.AudioSource -> future }"]],["AudioPlay",["Web.Audio"]],["DomNodeRender",["{ path : List.List Basics.Int, node : Web.DomTextOrElementHeader future }"]],["NotificationAskForPermission",[]],["NotificationShow",["{ id : String.String, message : String.String, details : String.String, on : Web.NotificationClicked -> future }"]],["HttpRequest",["Web.HttpRequest future"]],["TimePosixRequest",["Time.Posix -> future"]],["TimezoneOffsetRequest",["Basics.Int -> future"]],["TimeOnce",["{ pointInTime : Time.Posix, on : Time.Posix -> future }"]],["TimePeriodicallyListen",["{ intervalDurationMilliSeconds : Basics.Int, on : Time.Posix -> future }"]],["TimezoneNameRequest",["String.String -> 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"]],["WindowEventListen",["{ eventName : String.String, on : Json.Decode.Decoder future }"]],["WindowVisibilityChangeListen",["Web.WindowVisibility -> future"]],["WindowAnimationFrameListen",["Time.Posix -> future"]],["WindowPreferredLanguagesChangeListen",["List.List String.String -> future"]],["SocketConnect",["{ address : String.String, on : Web.SocketConnectionEvent -> future }"]],["SocketMessage",["{ id : Web.SocketId, data : String.String }"]],["SocketDisconnect",["Web.SocketId"]],["SocketMessageListen",["{ id : Web.SocketId, on : String.String -> future }"]],["LocalStorageSet",["{ key : String.String, value : Maybe.Maybe String.String }"]],["LocalStorageRequest",["{ key : String.String, on : Maybe.Maybe 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 }"]],["GeoLocationRequest",["Web.GeoLocation -> future"]],["GeoLocationChangeListen",["Web.GeoLocation -> future"]],["GamepadsRequest",["Dict.Dict Basics.Int Web.Gamepad -> future"]],["GamepadsChangeListen",["Dict.Dict Basics.Int Web.Gamepad -> future"]]]},{"name":"InterfaceSingleEdit","comment":" Individual message to js to sync up with the latest interface type,\ndescribing changes to an existing interface with the same identity\n","args":[],"cases":[["EditDom",["{ path : List.List Basics.Int, replacement : Web.DomEdit }"]],["EditAudio",["{ url : String.String, startTime : Time.Posix, replacement : Web.AudioEdit }"]],["EditNotification",["{ id : String.String, message : String.String, details : String.String }"]]]},{"name":"NotificationClicked","comment":" The user clicked a displayed notification,\nmoving the focus to our page\n","args":[],"cases":[["NotificationClicked",[]]]},{"name":"ProgramEvent","comment":" The \"msg\" in a [`Web.program`](#program)\n","args":["appState"],"cases":[["JsEventFailedToDecode",["Json.Decode.Error"]],["JsEventEnabledConstructionOfNewAppState",["appState"]]]},{"name":"ProgramState","comment":" The \"model\" in a [`Web.program`](#program)\n","args":["appState"],"cases":[["State",["{ interface : FastDict.Dict String.String (Web.InterfaceSingle appState), appState : appState }"]]]},{"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":"DomElementHeader","comment":" Everything about a [tagged DOM element](Web-Dom#Element)\nexcept potential sub-[node](Web-Dom#Node)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, stringProperties : Dict.Dict String.String String.String, boolProperties : Dict.Dict String.String Basics.Bool, 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 } }"},{"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\nUse [`Web.Http.addHeaders`](Web-Http#addHeaders) to set custom headers as needed.\nUse [`Web.Time.onceAt`](Web-Time#onceAt) to add a timeout of how long 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 }"},{"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).\nTo change the value that comes back in the future, use [`Web.interfaceFutureMap`](Web#interfaceFutureMap)\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`](#program)\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":"interfaceBatch","comment":" Combine multiple [`Interface`](#Interface)s into one\n","type":"List.List (Web.Interface future) -> Web.Interface 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.Dom.Node 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":"interfaceSingleEdits","comment":" What [`InterfaceSingleEdit`](#InterfaceSingleEdit)s are needed to sync up\n","type":"{ old : Web.InterfaceSingle future, updated : Web.InterfaceSingle future } -> List.List Web.InterfaceSingleEdit"},{"name":"program","comment":" Create a [`Program`](#Program):\n\n - The state is everything the program knows (what The Elm Architecture calls model).\n And it always starts with a given `initialState`\n\n - The [`Interface`](#Interface) is the face to the outside world\n and can be created using the helpers in [`Web.Dom`](Web-Dom), [`Web.Time`](Web-Time), [`Web.Http`](Web-Http) etc.\n The given `interface` function constructs these interfaces based on the current state\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","type":"{ 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) } } -> 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 [`Audio.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\n (Web.Audio.Parameter.at (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\n`Web.Audio.pan -0.9` for example 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 nodes](#Node) as part of an [`Interface`](Web#Interface).\n\nThese are primitives used for [svg](Web-Svg) and html\n(filling the same role as [`elm/virtual-dom`](https://dark.elm.dmy.fr/packages/elm/virtual-dom/latest/))\n\n@docs Node, text\n@docs Element, element, elementNamespaced\n@docs futureMap, render\n@docs Modifier, modifierFutureMap, modifierBatch, modifierNone\n@docs attribute, attributeNamespaced, style, boolProperty, stringProperty\n@docs listenTo, listenToPreventingDefaultAction\n@docs scrollToShow, scrollPositionRequest, scrollToPosition\n\n\n## internals, safe to ignore for users\n\nExposed so can for example simulate it more easily in tests, add a debugger etc.\n\n@docs ModifierSingle\n\n","unions":[{"name":"ModifierSingle","comment":" An individual [`Modifier`](#Modifier).\nCreate using [`attribute`](#attribute), [`style`](#style), [`listenTo`](#listenTo) etc.\n","args":["future"],"cases":[["Attribute",["{ namespace : Maybe.Maybe String.String, key : String.String, value : String.String }"]],["StringProperty",["{ key : String.String, value : String.String }"]],["BoolProperty",["{ key : String.String, value : Basics.Bool }"]],["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 }"]]]},{"name":"Node","comment":" Plain text or an [`Element`](#Element). Create using [`text`](#text) and [`element`](#element)\n","args":["future"],"cases":[["Text",["String.String"]],["Element",["Web.Dom.Element future"]]]}],"aliases":[{"name":"Element","comment":" A tagged DOM node that can itself contain child [node](#Node)s\n","args":["future"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { header : Web.DomElementHeader future, subs : List.List (Web.Dom.Node future) }"},{"name":"Modifier","comment":" Setting of a [`Web.Dom.Element`](Web-Dom#Element).\nTo create one, use [`attribute`](#attribute), [`style`](#style), [`listenTo`](#listenTo) etc.\nTo combine multiple, use [`Web.Dom.modifierBatch`](#modifierBatch) and [`Web.Dom.modifierNone`](#modifierNone)\n\nFor example to get `<a href=\"https://elm-lang.org\">elm</a>`\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\n## attribute vs property\n\n - attribute: part of the HTML itself. E.g. `class` in `<div class=\"greeting\"></div>`\n - property: an actual field on that js DOM object. E.g. `className` in `div.className = \"greeting\"`\n\nBut don't be surprised: There are cases where\n\n - only a property _or_ an attribute of a name exists\n - both exist but they have different effects\n\nFor example, trying to reset the text inside a a text input with\n\n Web.Dom.attribute \"value\" \"user input\"\n\n -- then later replace it with\n Web.Dom.attribute \"value\" \"\"\n\nwill only provide a _default value_ and has no effect on the currently written text,\nso you'll have to use\n\n Web.Dom.stringProperty \"value\" \"\"\n\nSimilarly for checkboxes:\n\n Web.Dom.boolProperty \"checked\" False\n\nMaybe a rule of thumb is:\nUse properties to set anything related to interactivity\nand attributes for everything else.\n\nIf you have some opinions or better explanations,\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":"boolProperty","comment":" A key-bool value DOM property [`Modifier`](#Modifier)\n","type":"String.String -> Basics.Bool -> Web.Dom.Modifier future_"},{"name":"element","comment":" Create a DOM element with a given tag, [`Modifier`](#Modifier)s and sub-[node](Web-Dom#Node)s.\nFor example to get `<p>flying</p>`\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.Dom.Node future) -> Web.Dom.Node future"},{"name":"elementNamespaced","comment":" Create a DOM element with a given namespace, tag, [`Modifier`](#Modifier)s and sub-[node](Web-Dom#Node)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.Dom.Node future) -> Web.Dom.Node future"},{"name":"futureMap","comment":" Wire events from this [`Web.Dom.Node`](Web-Dom#Node) to a specific event, for example\n\n buttonUi \"start\"\n |> Web.Dom.futureMap (\\Clicked -> StartButtonClicked)\n\nwith\n\n buttonUi : String -> Web.Dom.Node ButtonEvent\n buttonUi label =\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.Dom.Node future -> Web.Dom.Node mappedFuture"},{"name":"listenTo","comment":" Listen for a specific DOM event on the [`Web.Dom.Element`](Web-Dom#Element).\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 [`Web.Dom.Node`](Web-Dom#Node)\n","type":"Web.Dom.Node 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":"stringProperty","comment":" A key-string value DOM property [`Modifier`](#Modifier)\n","type":"String.String -> String.String -> 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 [DOM `Node`](#Node)\n","type":"String.String -> Web.Dom.Node 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<https://stackoverflow.com/a/51483510>\n\nIf you have issues with unresponsiveness, [open an issue](https://github.com/lue-bird/elm-state-interface/issues/new)\n\n","type":"Web.Interface (Dict.Dict Basics.Int Web.Gamepad)"},{"name":"request","comment":" An [`Interface`](Web#Interface) for getting 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.\n\n","type":"Web.Interface (Dict.Dict Basics.Int Web.Gamepad)"}],"binops":[]},{"name":"Web.GeoLocation","comment":" Observe the [`GeoLocation`](Web#GeoLocation) as part of an [`Interface`](Web#Interface)\nusing the [web geolocation API](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API).\n\n@docs request, changeListen\n\n","unions":[],"aliases":[],"values":[{"name":"changeListen","comment":" An [`Interface`](Web#Interface) for detecting changes in the current [position of the device](Web#GeoLocation)\n","type":"Web.Interface Web.GeoLocation"},{"name":"request","comment":" An [`Interface`](Web#Interface) for getting the current [position of the device](Web#GeoLocation)\n","type":"Web.Interface Web.GeoLocation"}],"binops":[]},{"name":"Web.Http","comment":" Helpers for [HTTP types](Web#HttpRequest) as part of an [`Interface`](Web#Interface)\n\n@docs request\n@docs get, post, addHeaders\n@docs expectString, expectJson, expectBytes, expectWhatever\n@docs bodyJson, bodyBytes\n\n","unions":[],"aliases":[],"values":[{"name":"addHeaders","comment":" Add custom headers to the [`HttpRequest`](Web#HttpRequest).\n\n request\n |> Web.Http.addHeaders\n [ ( \"X-Custom-Header\", \"ProcessThisImmediately\" )\n ]\n\n","type":"List.List ( String.String, String.String ) -> Web.HttpRequest future -> Web.HttpRequest future"},{"name":"bodyBytes","comment":" Put given [`Bytes`](https://dark.elm.dmy.fr/packages/elm/bytes/latest/) in the body of your request.\nThe string argument should be a [MIME type](https://en.wikipedia.org/wiki/Media_type) to be used in the `Content-Type` header\n\n import Bytes exposing (Bytes)\n import Bytes.Encode\n import Time\n import Web\n import Zip\n import Zip.Entry\n\n exampleZipBody : Web.HttpBody\n exampleZipBody =\n Web.Http.bodyBytes \"application/zip\"\n (Zip.fromEntries\n [ Bytes.Encode.string \"Hello, World!\"\n |> Bytes.Encode.encode\n |> Zip.Entry.store\n { path = \"hello.txt\"\n , lastModified = ( Time.utc, Time.millisToPosix 0 )\n , comment = Nothing\n }\n ]\n |> Zip.toBytes\n )\n\n - 🧩 [`Zip` and `Zip.Entry` are from `agu-z/elm-zip`](https://dark.elm.dmy.fr/packages/agu-z/elm-zip/latest/)\n\n","type":"String.String -> Bytes.Bytes -> Web.HttpBody"},{"name":"bodyJson","comment":" Put a given JSON value in the body of your request. This will automatically add the `Content-Type: application/json` header.\n","type":"Json.Encode.Value -> Web.HttpBody"},{"name":"expectBytes","comment":" Expect the response body to be [`Bytes`](https://dark.elm.dmy.fr/packages/elm/bytes/latest/).\nThe result will either be\n\n - `Err` with an [`HttpError`](Web#HttpError) if it didn't succeed\n - `Ok` with the `Bytes`\n\n","type":"Web.HttpExpect (Result.Result Web.HttpError Bytes.Bytes)"},{"name":"expectJson","comment":" Expect the response body to be `JSON`, decode it using the given decoder.\nThe result will either be\n\n - `Err` with an [`HttpError`](Web#HttpError) if it didn't succeed\n - `Ok` if there was a result with either\n - `Ok` with the decoded value\n - `Err` with a [`Json.Decode.Error`](https://dark.elm.dmy.fr/packages/elm/json/latest/Json-Decode#Error)\n and the actual text response\n\n","type":"Json.Decode.Decoder future -> Web.HttpExpect (Result.Result Web.HttpError (Result.Result { actualBody : String.String, jsonError : Json.Decode.Error } future))"},{"name":"expectString","comment":" Expect the response body to be a `String`.\n","type":"Web.HttpExpect (Result.Result Web.HttpError String.String)"},{"name":"expectWhatever","comment":" Discard the response body.\n","type":"Web.HttpExpect (Result.Result Web.HttpError ())"},{"name":"get","comment":" Create a `GET` [`HttpRequest`](Web#HttpRequest).\n\nUse [`Web.Http.addHeaders`](Web-Http#addHeaders) to set custom headers as needed.\nUse [`Web.Time.onceAt`](Web-Time#onceAt) to add a timeout of how long you are willing to wait before giving up.\n\n","type":"{ url : String.String, expect : Web.HttpExpect future } -> Web.HttpRequest future"},{"name":"post","comment":" Create a `POST` [`HttpRequest`](Web#HttpRequest).\n\nUse [`Web.Http.addHeaders`](Web-Http#addHeaders) to set custom headers as needed.\nUse [`Web.Time.onceAt`](Web-Time#onceAt) to add a timeout of how long you are willing to wait before giving up.\n\n","type":"{ url : String.String, body : Web.HttpBody, expect : Web.HttpExpect future } -> Web.HttpRequest future"},{"name":"request","comment":" An [`Interface`](Web#Interface) for handling an [`HttpRequest`](Web#HttpRequest)\nusing the [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)\n","type":"Web.HttpRequest future -> Web.Interface future"}],"binops":[]},{"name":"Web.LocalStorage","comment":" Saved data for the url origin (protocol, host name, port) across browser sessions.\n\nThis data doesn't expire and won't be cleared when the page is closed.\nThe only exception is \"incognito mode\", where all data is cleared once the last \"private\" tab is closed.\n\nsee [mdn on `Window.localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)\n\n@docs request, set, remove\n@docs setOnADifferentTabListen, removeOnADifferentTabListen\n\n","unions":[],"aliases":[],"values":[{"name":"remove","comment":" An [`Interface`](Web#Interface) for deleting the entry with the given key if it exists.\n\nNote: This will trigger an event for all other tabs of the same url origin\nthat can be listened to using [`removeOnADifferentTabListen`](#removeOnADifferentTabListen)\n\n","type":"String.String -> Web.Interface future_"},{"name":"removeOnADifferentTabListen","comment":" An [`Interface`](Web#Interface) for keeping an eye on\nwhen the local storage on a different tab with the same url origin is removed.\n","type":"String.String -> Web.Interface AppUrl.AppUrl"},{"name":"request","comment":" An [`Interface`](Web#Interface) for reading the value of the entry with the given key.\nComes back with `Nothing` if that key doesn't exist.\n\n import Json.Decode\n import Web\n\n projectFromLocalStorageRequest : Web.Interface (Result String Project)\n projectFromLocalStorageRequest =\n Web.LocalStorage.request \"project\"\n |> Web.interfaceFutureMap\n (\\savedProject ->\n case savedProject of\n Nothing ->\n \"nothing had been saved\" |> Err\n\n Just savedProjectJsonString ->\n savedProjectJsonString\n |> Json.Decode.decodeString projectJsonDecoder\n |> Result.mapError Json.Decode.errorToString\n )\n\n","type":"String.String -> Web.Interface (Maybe.Maybe String.String)"},{"name":"set","comment":" An [`Interface`](Web#Interface) for replacing the value of the entry with the given key\nor adding key and value as a new entry if the key doesn't exist.\n\n import Json.Decode\n import Web\n\n projectSaveToLocalStorage : Project -> Web.Interface future_\n projectSaveToLocalStorage =\n \\project ->\n Web.LocalStorage.set \"project\"\n (project |> projectJsonEncode |> Json.Encode.encode 0)\n\nNote: This will trigger an event for all other tabs of the same url origin\nthat can be listened to using [`setOnADifferentTabListen`](#setOnADifferentTabListen)\n\n","type":"String.String -> String.String -> Web.Interface future_"},{"name":"setOnADifferentTabListen","comment":" An [`Interface`](Web#Interface) for keeping an eye on\nwhen the local storage on a different tab with the same url origin is set.\n\nWhen the `oldValue` is `Nothing`, no entry with that key existed.\n\n","type":"String.String -> Web.Interface { appUrl : AppUrl.AppUrl, oldValue : Maybe.Maybe String.String, newValue : String.String }"}],"binops":[]},{"name":"Web.Navigation","comment":" Helpers for `history` interaction as part of an [`Interface`](Web#Interface)\n\n@docs urlRequest\n@docs pushUrl, replaceUrl\n@docs moveForward, moveBack, movementListen\n@docs load, reload\n\n","unions":[],"aliases":[],"values":[{"name":"load","comment":" An [`Interface`](Web#Interface) for leaving the current page and loading the given [URL](https://dark.elm.dmy.fr/packages/elm/url/latest/).\nThis always results in a page load, even if the provided URL is the same as the current one.\n\n gotoElmWebsite : Web.Interface future_\n gotoElmWebsite =\n Web.Navigation.load \"https://elm-lang.org/\"\n\nReplacement for [`Browser.Navigation.load`](https://dark.elm.dmy.fr/packages/elm/browser/latest/Browser-Navigation#load)\n\n","type":"String.String -> Web.Interface future_"},{"name":"moveBack","comment":" An [`Interface`](Web#Interface) for going back a given number of pages.\n\nNote: You only manage the browser history that you created.\n\nReplacement for [`Browser.Navigation.back`](https://dark.elm.dmy.fr/packages/elm/browser/latest/Browser-Navigation#back)\n\n","type":"Basics.Int -> Web.Interface future_"},{"name":"moveForward","comment":" An [`Interface`](Web#Interface) for going forward a given number of pages.\nIf there are no more pages in the future, this will do nothing.\n\nNote: You only manage the browser history that you created.\n\nReplacement for [`Browser.Navigation.forward`](https://dark.elm.dmy.fr/packages/elm/browser/latest/Browser-Navigation#forward)\n\n","type":"Basics.Int -> Web.Interface future_"},{"name":"movementListen","comment":" If you used [`pushUrl`](#pushUrl) to update the URL with new history entries,\nwhen the user clicks ← or → buttons (or you call [`moveForward`](#moveForward) or [`moveBack`](#moveBack) yourself),\nthe URL will change but your UI will not.\n\n[`movementListen`](#movementListen) is an [`Interface`](Web#Interface) for detecting those URL changes and making ui changes as needed.\n\nWhen the app itself initiates a url change with [`pushUrl`](#pushUrl) or [`replaceUrl`](#replaceUrl), no such event is triggered.\n\nNote: This event is called [\"popstate\"](https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event) in js\n\n","type":"Web.Interface AppUrl.AppUrl"},{"name":"pushUrl","comment":" An [`Interface`](Web#Interface) for changing the [app-specific URL](https://dark.elm.dmy.fr/packages/lydell/elm-app-url/latest/)\nand adding a new entry to the browser history\nwithout triggering a page load.\n\nReplacement for [`Browser.Navigation.pushUrl`](https://dark.elm.dmy.fr/packages/elm/browser/latest/Browser-Navigation#pushUrl)\n\n","type":"AppUrl.AppUrl -> Web.Interface future_"},{"name":"reload","comment":" An [`Interface`](Web#Interface) for reloading the current page.\nThis always results in a page load!\n\nNote: This may grab resources from the browser cache.\n\nReplacement for [`Browser.Navigation.reload`](https://dark.elm.dmy.fr/packages/elm/browser/latest/Browser-Navigation#reload)\n\n","type":"Web.Interface future_"},{"name":"replaceUrl","comment":" An [`Interface`](Web#Interface) for changing the [app-specific URL](https://dark.elm.dmy.fr/packages/lydell/elm-app-url/latest/),\nwithout triggering a page load or adding a new entry to the browser history.\n\nThis can be useful if you have search box and you want the ?search=hats in the 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 the same page!\n\nReplacement for [`Browser.Navigation.replaceUrl`](https://dark.elm.dmy.fr/packages/elm/browser/latest/Browser-Navigation#replaceUrl)\n\n","type":"AppUrl.AppUrl -> Web.Interface future_"},{"name":"urlRequest","comment":" An [`Interface`](Web#Interface) for getting the current page's [app-specific URL](https://dark.elm.dmy.fr/packages/lydell/elm-app-url/latest/).\nIs usually used while starting up the app.\n\nNote: Uses [`window.location.href`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location)\n\n","type":"Web.Interface AppUrl.AppUrl"}],"binops":[]},{"name":"Web.Notification","comment":" Give important notices to the user as push notifications.\nConsider this a convenience feature, not something users have to rely upon.\nAlways offer users alternative methods to view messages or initiate actions\nand allow users to opt out of getting more in the future.\n\n@docs askForPermission, show\n\nYou can combine it with [`Web.Window.visibilityChangeListen`](Web-Window#visibilityChangeListen)\nto only notify users when they're on a different page\n\n import Web\n\n type State\n = State\n { windowVisibility : Web.WindowVisibility\n , whoseMove : Player\n , mode : Mode\n , notificationPermissionToggle : Permission\n }\n\n type Permission\n = Rejected\n | Accepted\n\n type Mode\n = LongGameBoardMode\n | SettingsPage\n\n type Player\n = You\n | Opponent\n\n interface : State -> Web.Interface State\n interface =\n \\(State state) ->\n [ case state.notificationPermissionToggle of\n Accepted ->\n Web.Notification.askForPermission\n\n Rejected ->\n Web.interfaceNone\n , case ( state.windowVisibility, state.whoseTurn ) of\n ( Web.WindowHidden, You ) ->\n Web.Notification.show\n { message = \"opponent moved\", ... }\n |> Web.interfaceFutureMap\n (\\Web.NotificationClicked ->\n -- return to the game if previously in settings\n State { state | mode = LongGameBoardMode }\n )\n\n ( Web.WindowHidden, Opponent ) ->\n Web.interfaceNone\n\n ( Web.WindowShown, _ ) ->\n Web.interfaceNone\n , case state.mode of\n LongGameBoardMode ->\n ..listen for opponent move from server..\n |> Web.interfaceFutureMap\n (\\... -> State { state | whoseMove = You })\n\n SettingsPage ->\n ..toggle for accepting/rejecting notifications..\n |> Web.interfaceFutureMap\n (\\... -> State { state | notificationPermissionToggle = ..opposite.. })\n ]\n |> Web.interfaceBatch\n\n","unions":[],"aliases":[],"values":[{"name":"askForPermission","comment":" Ask the user to consent to receiving notifications, if they haven't already.\n\nFor security reasons, browsers require some kind of user interaction like a button click first.\nSo you could for example add a toggle to send notifications and ask only for permission\nwhen the toggle is set.\n\n","type":"Web.Interface future_"},{"name":"show","comment":" An [`Interface`](Web#Interface) for pushing a notification to the user.\nUsers can in the future [respond to it by clicking it](Web#NotificationClicked).\n\nTo not notify users multiple times for multiple messages of the same kind,\nchoose an `id` with a description for this kind\nso that the notification with the same kind gets silently replaced if it exists.\n\n case messagesFromOpponent of\n [] ->\n Web.interfaceNone\n\n [ onlyMessage ] ->\n Web.Notification.show\n { id = \"opponent messages\"\n , message = \"Your opponent left a message\"\n , details = \"\\\"\" ++ onlyMessage ++ \"\\\"\"\n }\n\n _ :: _ :: message2Up ->\n Web.Notification.show\n { id = \"opponent messages\"\n , message =\n [ \"Your opponent left \"\n , 2 + (message2Up |> List.length) |> String.fromInt\n , \" messages\"\n ]\n |> String.join\n , details = \"\"\n }\n\nAnother example of a reminder shown in advance\n\n let\n untilMeeting : Duration\n untilMeeting =\n Duration.from meetingTime currentTime\n in\n if untilMeeting |> Quantity.isLessThan (Duration.minutes 10) then\n Web.Notification.show\n { id = \"time until meeting\"\n , message =\n [ \"the meeting starts in \"\n , untilMeeting |> Duration.inMinutes |> Basics.ceiling |> String.fromInt)\n , \" minutes\"\n ]\n |> String.concat\n , details = \"\"\n }\n\n else\n Web.interfaceNone\n\nNote: If you haven't previously used [`askForPermission`](#askForPermission)\nit will request this permission now.\n\n","type":"{ message : String.String, details : String.String, id : String.String } -> Web.Interface Web.NotificationClicked"}],"binops":[]},{"name":"Web.Random","comment":" Helpers for randomness as part of an [`Interface`](Web#Interface).\nNot familiar with random \"generators\"? [`elm/random`](https://package.elm-lang.org/packages/elm/random/latest)\nexplains it nicely!\n\nHere's an example showing a number between 1 and 6 and a button to reroll\nusing [NoRedInk/elm-random-pcg-extended](https://dark.elm.dmy.fr/packages/NoRedInk/elm-random-pcg-extended/latest/)\n\n import Random.Pcg.Extended\n import Web.Dom\n\n type State\n = WaitingForInitialRandomness\n | DiceUiState { diceEyes : Int, seed : Random.Pcg.Extended.Seed }\n\n type DiceUiEvent\n = RerollClicked\n\n diceEyesRandomGenerator : Random.Pcg.Extended.Generator Int\n diceEyesRandomGenerator =\n Random.Pcg.Extended.int 1 6\n\n { initialState = WaitingForInitialRandomness\n , interface =\n \\state ->\n case state of\n WaitingForInitialRandomness ->\n Web.Random.unsignedInt32s 4\n |> Web.interfaceFutureMap\n (\\unsignedInt32s ->\n let\n initialSeed : Random.Pcg.Extended.Seed\n initialSeed =\n Random.Pcg.Extended.initialSeed (unsignedInt32s |> List.head |> Maybe.withDefault 0) (unsignedInt32s |> List.drop 1)\n\n ( diceEyes, newSeed ) =\n Random.Pcg.Extended.step diceEyesRandomGenerator initialSeed\n in\n DiceUiState { diceEyes = diceEyes, seed = newSeed }\n )\n\n DiceUiState randomStuff ->\n Web.Dom.element \"div\"\n []\n [ randomStuff.diceEyes |> String.fromInt |> Web.Dom.text\n , Web.Dom.element \"button\"\n [ Web.Dom.listenTo \"click\"\n |> Web.Dom.modifierFutureMap (\\_ -> RerollClicked)\n ]\n [ Web.Dom.text \"roll the dice\" ]\n ]\n |> Web.Dom.render\n |> Web.interfaceFutureMap\n (\\RerollClicked ->\n let\n ( diceEyes, newSeed ) =\n Random.Pcg.Extended.step diceEyesRandomGenerator randomStuff.seed\n in\n DiceUiState { diceEyes = diceEyes, seed = newSeed }\n )\n }\n\n@docs unsignedInt32s\n\n","unions":[],"aliases":[],"values":[{"name":"unsignedInt32s","comment":" An [`Interface`](Web#Interface) for generating a given count of cryptographically sound unsigned 32-bit `Int`s.\nYou can use these in all kinds of packages that allow creating an initial seed\nfrom ints like [NoRedInk/elm-random-pcg-extended](https://dark.elm.dmy.fr/packages/NoRedInk/elm-random-pcg-extended/latest/Random-Pcg-Extended#initialSeed)\n\nNote: uses [`window.crypto.getRandomValues`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues)\n\n","type":"Basics.Int -> Web.Interface (List.List Basics.Int)"}],"binops":[]},{"name":"Web.Socket","comment":" Helpers for [Socket types](Web#socket) as part of an [`Interface`](Web#Interface)\n\n\n## connection\n\n@docs connectTo, disconnect\n\n\n## communicate\n\n@docs message, messageListen\n\n","unions":[],"aliases":[],"values":[{"name":"connectTo","comment":" An [`Interface`](Web#Interface) for opening a connection on a given address,\nnotifying you when it's [connected or disconnected](Web#SocketConnectionEvent)\n\nOnce this detects it's available, make sure to set your state's [`SocketId`](Web#SocketId) so you can actually [send](#message)\nand [receive](#messageListen) messages.\nAnd once it's disconnected, set your state's [`SocketId`](Web#SocketId) back to nothing:\n\n case state.socketId of\n Nothing ->\n Web.Socket.connectTo \"ws://127.0.0.1:9000\"\n |> Web.interfaceMap\n (\\connectionChanged ->\n case connectionChanged of\n Web.SocketConnected socketId ->\n { state | socketId = socketId |> Just }\n\n Web.SocketDisconnected ->\n { state | socketId = Nothing }\n )\n\n Just socketId ->\n Web.Socket.message socketId \"Meow\"\n\n","type":"String.String -> Web.Interface Web.SocketConnectionEvent"},{"name":"disconnect","comment":" An [`Interface`](Web#Interface) for closing a given connection\n","type":"Web.SocketId -> Web.Interface future_"},{"name":"message","comment":" An [`Interface`](Web#Interface) for sending data to the server.\n\nIt's common to pair this with [`Json.Encode.encode 0`](https://dark.elm.dmy.fr/packages/elm/json/latest/Json-Encode#encode)\nto send json.\n\n","type":"Web.SocketId -> String.String -> Web.Interface future_"},{"name":"messageListen","comment":" An [`Interface`](Web#Interface) for detecting when data has been sent from the server\n","type":"Web.SocketId -> Web.Interface String.String"}],"binops":[]},{"name":"Web.Svg","comment":" Helpers for svg [DOM nodes](Web-Dom#Node)\n\n@docs element\n\nfor text, attributes etc use the helpers in [`Web.Dom`](Web-Dom)\n\n","unions":[],"aliases":[],"values":[{"name":"element","comment":" Create an SVG element [`Web.Dom.Node`](Web-Dom#Node).\nwith a given tag, [`Modifier`](Web-Dom#Modifier)s and sub-nodes\n","type":"String.String -> List.List (Web.Dom.Modifier future) -> List.List (Web.Dom.Node future) -> Web.Dom.Node future"}],"binops":[]},{"name":"Web.Time","comment":" Helpers for [`elm/time`](https://dark.elm.dmy.fr/packages/elm/time/) primitives as part of an [`Interface`](Web#Interface).\n\n@docs posixRequest, zoneRequest, zoneNameRequest\n@docs periodicallyListen, onceAt\n\n","unions":[],"aliases":[],"values":[{"name":"onceAt","comment":" An [`Interface`](Web#Interface) for getting a reminder\nonce a given [point in time](https://dark.elm.dmy.fr/packages/elm/time/latest/Time#Posix) has been reached.\n\nThis lets you for example wait until it's 15 minutes before the event,\ntimeout a request or schedule a certain action to a specific time.\n\n import Web\n\n type RequestState result\n = NotAsked\n | BeforeTimeout { start : Time.Posix }\n | TimedOut\n | GotResult result\n\n { initialState = NotAsked\n , interface =\n \\state ->\n [ case state of\n NotAsked ->\n [ Web.Time.posixRequest\n |> Web.interfaceFutureMap BeforeTimeout\n , ..request.. |> Web.futureMap GotResult\n ]\n\n BeforeTimeout requestTime ->\n -- timeout after 10 seconds\n Web.Time.onceAt (Duration.addTo requestTime (Duration.seconds 10))\n |> Web.interfaceFutureMap (\\_ -> TimedOut)\n\n TimedOut ->\n ...\n\n GotResult result ->\n ...\n ]\n }\n\n - 🧩 [`Duration` is from ianmackenzie/elm-units](https://dark.elm.dmy.fr/packages/ianmackenzie/elm-units/latest/Duration)\n\nYou can abstract this in various ways like adding a\n\n withTimeout :\n ..Request result..\n -> Web.Interface (RequestState result)\n\nwhere the result can be put into the \"main state\" and therefore cased on.\n\n","type":"Time.Posix -> Web.Interface Time.Posix"},{"name":"periodicallyListen","comment":" An [`Interface`](Web#Interface) for getting the current time\nevery time a given [`Duration`](https://dark.elm.dmy.fr/packages/ianmackenzie/elm-units/latest/Duration) has passed.\n\nNote: Do not use it for animations.\n[`Web.Window.animationFrameListen`](Web-Window#animationFrameListen)\nsyncs up with repaints and will end up being much smoother for any moving visuals.\n\n","type":"Duration.Duration -> Web.Interface Time.Posix"},{"name":"posixRequest","comment":" An [`Interface`](Web#Interface) for getting the current [POSIX time](https://dark.elm.dmy.fr/packages/elm/time/latest/Time#Posix).\n\nReplacement for [`elm/time`'s `Time.now`](https://dark.elm.dmy.fr/packages/elm/time/latest/Time#now).\n\n","type":"Web.Interface Time.Posix"},{"name":"zoneNameRequest","comment":" Intended for package authors.\nAn [`Interface`](Web#Interface) for using [`Intl.DateTimeFormat().resolvedOptions().timeZone`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/resolvedOptions#timezone)\nto get names like `Europe/Moscow` or `America/Havana`.\nFrom there you can look it up in any [IANA data](https://www.iana.org/time-zones) you loaded yourself.\n\nReplacement for [`elm/time`'s `Time.getZoneName`](https://package.elm-lang.org/packages/elm/time/latest/Time#getZoneName).\n\n","type":"Web.Interface String.String"},{"name":"zoneRequest","comment":" An [`Interface`](Web#Interface) for getting a [`Time.Zone`](https://dark.elm.dmy.fr/packages/elm/time/latest/Time#Zone)\nbased on the current UTC offset.\n\nReplacement for [`elm/time`'s `Time.here`](https://dark.elm.dmy.fr/packages/elm/time/latest/Time#here).\n\n","type":"Web.Interface Time.Zone"}],"binops":[]},{"name":"Web.Window","comment":" Observe and alter the page's global environment as part of an [`Interface`](Web#Interface)\n\n@docs animationFrameListen, visibilityChangeListen\n@docs sizeRequest, resizeListen\n@docs preferredLanguagesRequest, preferredLanguagesChangeListen\n@docs documentListenTo, listenTo\n\nWhen navigating to a new page on the same site,\nyou may want to change the document's context:\n\n@docs titleReplaceBy, authorSet, keywordsSet, descriptionSet\n\n","unions":[],"aliases":[],"values":[{"name":"animationFrameListen","comment":" An [`Interface`](Web#Interface) for detecting when animation frames occur.\nThis will be about 60 times per second, though 75, 120, and 144 are also widely used.\nTo balance this out in your animation, the [current time](https://dark.elm.dmy.fr/packages/elm/time/latest/Time#Posix) is provided each frame.\n\nTo get a delta, you could use [`Web.Time.posixRequest`](Web-Time#posixRequest)\nto get a start time and check with e.g. [`Duration.from`](https://dark.elm.dmy.fr/packages/ianmackenzie/elm-units/latest/Duration#from) how far you've progressed in the timeline.\n\nNote: To improve performance and battery life, most browsers pause these notifications when the app is running in a background tab or a hidden `<iframe>`.\n\nReplacement for [`Browser.Events.onAnimationFrame`](https://dark.elm.dmy.fr/packages/elm/browser/latest/Browser-Events#onAnimationFrame)\n\nNote: uses [`window.requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame).\n\n","type":"Web.Interface Time.Posix"},{"name":"authorSet","comment":" An [`Interface`](Web#Interface) for adding or replacing the document's author metadata\n","type":"String.String -> Web.Interface future_"},{"name":"descriptionSet","comment":" An [`Interface`](Web#Interface) for adding or replacing the document's description metadata\nwhich should be a short and accurate summary of the content of the page.\nSeveral browsers, like Firefox and Opera, use this as the default description of bookmarked pages.\n","type":"String.String -> Web.Interface future_"},{"name":"documentListenTo","comment":" An [`Interface`](Web#Interface) for detecting a specific [`document` event](https://developer.mozilla.org/en-US/docs/Web/API/Document#events)\nthat has no native [`Interface`](Web#Interface), like like scroll, scrollend, selectionchange or paste\n","type":"String.String -> Web.Interface Json.Decode.Value"},{"name":"keywordsSet","comment":" An [`Interface`](Web#Interface) for adding or replacing the document's keywords metadata\nwhich should consist of words relevant to the page's content\n","type":"List.List String.String -> Web.Interface future_"},{"name":"listenTo","comment":" An [`Interface`](Web#Interface) for detecting a specific [`window` event](https://developer.mozilla.org/en-US/docs/Web/API/Window#events)\n","type":"String.String -> Web.Interface Json.Decode.Value"},{"name":"preferredLanguagesChangeListen","comment":" An [`Interface`](Web#Interface) for detecting changes to the languages the user prefers.\nEach described using language tags according to [RFC 5646: Tags for Identifying Languages (also known as BCP 47)](https://datatracker.ietf.org/doc/html/rfc5646).\nIn the returned list they are ordered by preference with the most preferred language first.\n\nNote: uses [`window.onlanguagechange`](https://developer.mozilla.org/en-US/docs/Web/API/Window/languagechange_event)\n\n","type":"Web.Interface (List.List String.String)"},{"name":"preferredLanguagesRequest","comment":" An [`Interface`](Web#Interface) for reading the languages the user prefers.\nEach described using language tags according to [RFC 5646: Tags for Identifying Languages (also known as BCP 47)](https://datatracker.ietf.org/doc/html/rfc5646).\nIn the returned list they are ordered by preference with the most preferred language first.\n\nNote: uses [`window.navigator.languages`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages)\n\n","type":"Web.Interface (List.List String.String)"},{"name":"resizeListen","comment":" An [`Interface`](Web#Interface) for detecting changes to the inner window width and height\n","type":"Web.Interface { width : Basics.Int, height : Basics.Int }"},{"name":"sizeRequest","comment":" An [`Interface`](Web#Interface) for getting the inner window width and height in pixels,\nnot including toolbars/scrollbars\n","type":"Web.Interface { width : Basics.Int, height : Basics.Int }"},{"name":"titleReplaceBy","comment":" An [`Interface`](Web#Interface) for setting the document's title\n","type":"String.String -> Web.Interface future_"},{"name":"visibilityChangeListen","comment":" An [`Interface`](Web#Interface) for detecting changes to the [visibility to the user](Web#WindowVisibility)\n\nYou can use times where the page becomes hidden to for example pause a currently running game.\nThese times will also be the last reliable observation you can make before a user might close the page, so treat it as the likely end of the user's session\n\n","type":"Web.Interface Web.WindowVisibility"}],"binops":[]}]