h*,* 6      !"#$%&'()*+,-./0123450.2.0.1 Safe-Inferred "%)*<purviewThis is for creating events that should go to a parent handler, or sent back in to the same handler.6purviewThese encapsulate events that come from the front end in addition to events that are internal. For example, state changes or messages being sent to handlers higher up in the tree.7purviewfor example, "click" or "blur"8purview*This for events intended for the front end69:;7<=>?@AB8CDEFG Safe-InferredpurviewHow to run your algebraic effects or other. This will apply to all  effectHandlers.purviewSpecify what to do with logspurviewFor extending the handled events. By default it covers the usual click, change, focus(in/out) purviewThis is placed directly into the , so that you can link to external CSS etc purviewWhen enabled, Purview will send the whole tree on websocket reconnection. This enables you to use "ghcid --command 'stack ghci examples/Main.hs' --test :main`" to restart the server on file change, and get a kind of live reloading purviewthe port to run on purview1whether the websocket tries to connect using ws:/ or wss:/ locally you probably want this false, in prod secure of course    Safe-Inferred"%)* dpurviewThis is what you end up building using the various helpers. It's hopefully rare that you have to use these directly, but it may be useful to better understand what's happening behind the scenes.HpurviewThe location of the parent effect handler (provided by prepareTree)Ipurview=The location of this effect handler (provided by prepareTree)JpurviewThe initial stateKpurview5Receive an event, change the state, and send messagespurview"Attributes are collected until an HTML= constructor is hit, where they are applied during rendering.purview?part of creating handlers for different events, e.g. On "click"purviewhash of the css, the csspurviewfor creating new Attributes to put on HTML, e.g. Generic "type" "radio" for type="radio".LMKNOPHQIJRSTUVW Safe-Inferred"%')* Xpurview State -> (State -> State, [DirectedEvent parentEvent Event]) reducer event state = case event of "up" -> (const "down", []) "down" -> (const "up", []) toggleHandler :: (State -> Purview Event m) -> Purview parentEvent m toggleHandler = handler [] "up" reducer component :: Purview parentEvent m component = toggleHandler view Note that parentEvent is left unspecified as this handler doesn't send any events to a parent, so it can be plugged in anywhere. If you did want to send events, the reducer looks like this: reducer :: String -> String -> (String -> String, [DirectedEvent String String]) reducer event state = case event of "up" -> (const "down", [Self "down"]) "down" -> (const "up", [Parent "clickedDown"]) 3Which is about all there is to sending more events.purviewThis provides a shorthand for when you know you want to overwrite the state on each event.Example:?@ view direction = onClick "toggle" $ button [ text direction ]toggleHandler = handler' [] "up" reducer where reducer "toggle" state = let newState = if state == "up" then "down" else "up" -- note it's just newState, not const newState in (newState, [])component = toggleHandler viewpurviewThis handler gives you access to whichever monad you're running Purview with.Example:If you wanted to print something on the server every time someone clicked a button: view _ = onClick "sayHello" $ button [ text "Say hello on the server" ] handler = effectHandler [] () reduce where reduce "sayHello" state = do print "Someone on the browser says hello!" pure (const (), []) component = handler view purviewTo mirror handler', a shorthand for when you know you want to overwrite state.purviewFor receiving events from Javascript. In addition to the name and an event producer, the receiver takes in a state and child and passes it through for (hopefully) more natural composition with handlers.Example:This receives an event from javascript every 1 second and increments the count. component count = div [ text (show count) ] countHandler = handler' [] (0 :: Int) reducer where reducer "increment" state = (state + 1, []) reducer "decrement" state = (state - 1, []) countReceiver = receiver "incrementReceiver" (const "increment") render = countHandler . countReceiver $ component jsCounter = [r| const startCount = () => { window.setInterval(() => { -- sendEvent is added to the window by Purview and all that's -- needed. Purview finds the receiver by name. sendEvent("incrementReceiver", "increment") }, 1000) } startCount() |] main = serve defaultConfiguration { javascript=jsCounter } render (purviewFor adding an "id" to HTML)purviewFor adding a "class" to HTML+purviewFor adding inline styles. Good for dynamic parts of styling, as the style QuasiQuoter does not support variables.Example:Varying a color based on input: submitButton valid = let borderColor = if valid then "green" else "red" borderStyle = "border-color: " <> borderColor <> ";" in istyle borderStyle $ button [ text Submit ] ,purviewThis will send the event to the handler above it whenever "click" is triggered on the frontend. It will be bound to whichever concrete HTML is beneath it.Example:To send a string based event: toggleButton :: Purview String m toggleButton = onClick "toggle" $ button [] To send a better typed event: data Toggle = Toggle deriving (Show, Eq) toggleButton :: Purview Toggle m toggleButton = onClick Toggle $ button [] Note how the type changed to show which kind of event is produced.-purviewThis will send the event to the handler above it whenever "submit" is triggered on the frontend. It takes a function to transform the value received into an event for handlers, this can be a good spot to debug trace and see what is being received from the browser.The form produces JSON so the handling function can also be used to parse the form, or you can throw it up as a string for the handler to parse.Example: nameAttr = Attribute . Generic "name" data FormEvent = Submitted String deriving (Show, Eq) handleSubmit (Just val) = Submitted val handleSubmit Nothing = Submitted "" component :: Purview FormEvent m component = onSubmit handleSubmit $ form [ nameAttr "text" $ input [] ] .purviewThis is triggered on focusout instead of blur to work with mobile sites as well. Like onSubmit it takes a value.Example: data AddressEvent = LineOneUpdated String deriving (Show, Eq) handleBlur (Just val) = LineOneUpdated val handleBlur Nothing = LineOneUpdated "" addressLineOne = onBlur handleBlur $ input [] /purviewTriggered on changeExample: data AddressEvent = LineOneUpdated String deriving (Show, Eq) handleChange (Just val) = LineOneUpdated val handleChange Nothing = LineOneUpdated "" addressLineOne = onChange handleChange $ input [] purviewInitial events to firepurviewThe initial statepurview8The reducer, or how the state should change for an eventpurview*The continuation / component to connect topurviewInitial events to firepurviewThe initial statepurview8The reducer, or how the state should change for an eventpurview*The continuation / component to connect topurviewInitial events to firepurview initial statepurviewreducer (note the m!)purview continuationpurviewInitial events to firepurview initial statepurviewreducer (note the m!)purview continuation !"#$%&'()c*+,-./  Safe-Inferred#de  Safe-Inferred%#fghi  Safe-Inferred#jklmnopq  Safe-Inferred"%'%rpurviewThis walks through the tree and collects actions that should be run only once, and sets their run value to True. It's up to something else to actually send the actions.:It also assigns a location to message and effect handlers.srtu Safe-Inferred'%0purviewTakes the tree and turns it into HTML. Attributes are passed down to children until they reach a real HTML tag. vwxyz{|0} Safe-Inferred"%'%~ Safe-Inferred"(]1purviewComponents styled with this QuasiQuoter will have a class added to them and the CSS added to the stylesheet. Basic support is provided for easily styling nested components and for pseudo selectors. Examples:Styling a button: blue = [style| background-color: blue; |] blueButton = blue $ button [] Styling a list with a pseudo selector to get the right cursor on hover: listStyle = [style| width: 250px; li { padding: 25px; &:hover { cursor: pointer; } } |] list = listStyle $ ul [ li [ text "an item" ] ] 1 Safe-Inferred"%((1+ '$!"#%&*(),-./0(1+ '$!"#%&*(),-./0 Safe-Inferred") Safe-Inferred"')3purviewThis starts up the Warp server.Example: import Purview.Server view url = p [ text "hello world" ] main = serve defaultConfiguration view 3  2453  245 !" # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < =>?@ABCDEFGHIJKLMNOPQRFSTUVWXYZ[\]^_`abcdefghijklmfn o p q f r g s t u v w x y z { | f } ~purview-0.2.0.1-inplacePurviewPurview.ServerpurviewEvents Configuration Component EventHandlingDiffingComponentHelpers CleanTreeCollectInitials Paths_purview PrepareTree Rendering EventLoopStyleWrapper DirectedEventParentSelfBrowser interpreterloggereventsToListenTohtmlHeaddevMode javascriptportsecure AttributeHtml AttributesOnGenerichandlerhandler' effectHandlereffectHandler'receiverdivspanh1h2h3h4paullibuttonforminputtextid'class'hrefistyleonClickonSubmitonBluronChangerenderstyledefaultConfigurationserverenderFullPagestartWebSocketLoopEvent$sel:kind:FromFrontendEventForFrontEndEvent $sel:handlerId:FromFrontendEvent$sel:childId:FromFrontendEvent$$sel:childLocation:FromFrontendEvent$sel:event:FromFrontendEvent$sel:location:FromFrontendEvent$sel:value:FromFrontendEventJavascriptCallEventStateChangeEvent InternalEventFromFrontendEvent$sel:event:ForFrontEndEvent$sel:message:ForFrontEndEventParentIdentifier Identifier$sel:parentIdentifier:Attribute$sel:identifier:Attribute$sel:state:Attribute$sel:effectReducer:Attribute$sel:reducer:Attribute$sel:continuation:Attribute$sel:initialEvents:Attribute$sel:child:Attribute$sel:eventHandler:Attribute$sel:name:Attribute EffectHandlerReceiverHandlerTextValueHash applyNewStateLocationdirectedEventToInternalEvent findEventrunEventChangeAddDeleteUpdatediffclassesremoveClassCSS cleanTreegetStyleFromAttrcollectInitialsversion getBinDir getLibDir getDynLibDir getDataDir getLibexecDirgetDataFileName getSysconfDir prepareTreeaddLocationToAttr prepareTree'isOn isGenericisClassgetStylegetClassBasedStyle renderGenericrenderAttributesrender' eventLoop handleCSS parseLineparseCSSBraceOpenCloseNoneeventHandlerFn bindEventsFn eventHandlingeventBubblingHandlingwebsocketScriptsendEventHelper prepareCsswrapHtml