-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | ReactJS binding using Glazier.Command. -- -- ReactJS binding using Glazier.Commmand. Please see README.md. @package glazier-react @version 1.0.0.0 module Glazier.React.Component.Internal -- | Returns a reference to the javascript *class* definition of the shim -- wrapper around ReactPureComponent newtype ShimComponent ShimComponent :: JSRep -> ShimComponent -- | This returns the javascript class definition of ShimComponent. There -- is ever only one shim class, so it is purely available shimComponent :: ShimComponent -- | Rerenders an instance of a component created using ShimComponent. rerenderShim :: ComponentRef -> IO () -- | This is used store the react "ref" to a javascript instance of a react -- Component. newtype ComponentRef ComponentRef :: JSRep -> ComponentRef instance Control.DeepSeq.NFData Glazier.React.Component.Internal.ComponentRef instance Data.String.IsString Glazier.React.Component.Internal.ComponentRef instance JavaScript.Extras.Cast.ToJS Glazier.React.Component.Internal.ComponentRef instance GHCJS.Marshal.Internal.PToJSVal Glazier.React.Component.Internal.ComponentRef instance GHCJS.Internal.Types.IsJSVal Glazier.React.Component.Internal.ComponentRef instance GHC.Show.Show Glazier.React.Component.Internal.ComponentRef instance GHC.Generics.Generic Glazier.React.Component.Internal.ComponentRef instance Control.DeepSeq.NFData Glazier.React.Component.Internal.ShimComponent instance Data.String.IsString Glazier.React.Component.Internal.ShimComponent instance JavaScript.Extras.Cast.ToJS Glazier.React.Component.Internal.ShimComponent instance GHCJS.Marshal.Internal.PToJSVal Glazier.React.Component.Internal.ShimComponent instance GHCJS.Internal.Types.IsJSVal Glazier.React.Component.Internal.ShimComponent instance GHC.Show.Show Glazier.React.Component.Internal.ShimComponent instance GHC.Generics.Generic Glazier.React.Component.Internal.ShimComponent instance JavaScript.Extras.Cast.FromJS Glazier.React.Component.Internal.ComponentRef module Glazier.React.Component -- | Returns a reference to the javascript *class* definition of the shim -- wrapper around ReactPureComponent data ShimComponent -- | This returns the javascript class definition of ShimComponent. There -- is ever only one shim class, so it is purely available shimComponent :: ShimComponent -- | Rerenders an instance of a component created using ShimComponent. rerenderShim :: ComponentRef -> IO () -- | This is used store the react "ref" to a javascript instance of a react -- Component. data ComponentRef -- | HtmlT inspired monad for creating ReactElements module Glazier.React.Element -- | NB. No FromJS provided. See unsafeCoerceElement below. data ReactElement -- | Unfortunately, ReactJS did not export an easy way to check if -- something is a ReactElement, although they do so in the internal code -- with REACT_ELEMENT_TYPE. This function allow coercing a ReactElement -- from a JSVal and is named unsafe as a reminder that the coersion is -- unchecked. This function is required when receiving ReactElement from -- javascript (eg in a callback) or to interface with foreign React -- Elements. unsafeCoerceElement :: JSVal -> ReactElement -- | Create a react element (with children) from a HashMap of properties mkBranchElement :: JSRep -> [Property] -> [ReactElement] -> IO ReactElement -- | Create a react element (with no children) from a HashMap of properties mkLeafElement :: JSRep -> [Property] -> IO ReactElement -- | Not an IO action because JSString is immutable textElement :: JSString -> ReactElement -- | React only allows a single top most element. Provide a handly function -- to wrap a list of ReactElements inside a div if required. If -- there is only one element in the list, then nothing is changed. mkCombinedElements :: [ReactElement] -> IO ReactElement instance Control.DeepSeq.NFData Glazier.React.Element.ReactElement instance Data.String.IsString Glazier.React.Element.ReactElement instance JavaScript.Extras.Cast.ToJS Glazier.React.Element.ReactElement instance GHCJS.Marshal.Internal.PToJSVal Glazier.React.Element.ReactElement instance GHCJS.Internal.Types.IsJSVal Glazier.React.Element.ReactElement instance GHC.Show.Show Glazier.React.Element.ReactElement instance GHC.Generics.Generic Glazier.React.Element.ReactElement instance Control.Newtype.Generics.Newtype Glazier.React.Element.ReactElement -- | This module based on ReactFluxPropertiesAndEvents.hs. module Glazier.React.EventTarget.Internal -- | The object that dispatched the event. -- https://developer.mozilla.org/en-US/docs/Web/API/Event/target newtype EventTarget EventTarget :: JSRep -> EventTarget instance Control.DeepSeq.NFData Glazier.React.EventTarget.Internal.EventTarget instance Data.String.IsString Glazier.React.EventTarget.Internal.EventTarget instance JavaScript.Extras.Cast.ToJS Glazier.React.EventTarget.Internal.EventTarget instance GHCJS.Marshal.Internal.PToJSVal Glazier.React.EventTarget.Internal.EventTarget instance GHCJS.Internal.Types.IsJSVal Glazier.React.EventTarget.Internal.EventTarget instance GHC.Show.Show Glazier.React.EventTarget.Internal.EventTarget instance GHC.Generics.Generic Glazier.React.EventTarget.Internal.EventTarget instance JavaScript.Extras.Cast.FromJS Glazier.React.EventTarget.Internal.EventTarget -- | This module based on ReactFluxPropertiesAndEvents.hs. module Glazier.React.EventTarget -- | The object that dispatched the event. -- https://developer.mozilla.org/en-US/docs/Web/API/Event/target data EventTarget -- | HtmlT inspired monad for creating ReactElements module Glazier.React.Markup data ReactMarkup ElementMarkup :: ReactElement -> ReactMarkup TextMarkup :: JSString -> ReactMarkup BranchMarkup :: BranchParam -> ReactMarkup LeafMarkup :: LeafParam -> ReactMarkup -- | The parameters required to create a branch ReactElement with children data BranchParam BranchParam :: JSRep -> (DList Property) -> (DList ReactMarkup) -> BranchParam -- | The parameters required to create a leaf ReactElement (no children) data LeafParam LeafParam :: JSRep -> (DList Property) -> LeafParam -- | Create ReactElements from a ReactMarkup fromMarkup :: ReactMarkup -> IO ReactElement -- | To use an exisitng ReactElement fromElement :: MonadState (DList ReactMarkup) m => ReactElement -> m () -- | Convert the ReactMlt to [Z.ReactElement] toElements :: DList ReactMarkup -> IO [ReactElement] -- | Fully render the ReactMlt into a single Z.ReactElement toElement :: DList ReactMarkup -> IO ReactElement -- | For text content txt :: MonadState (DList ReactMarkup) m => JSString -> m () -- | For the contentless elements: eg br_. Memonic: lf for leaf. -- Duplicate listeners with the same key will be combined, but it is a -- silent error if the same key is used across listeners and props. "If -- an attribute/prop is duplicated the last one defined wins." -- https://www.reactenlightenment.com/react-nodes/4.4.html lf :: (MonadState (DList ReactMarkup) m) => JSRep -> (DList Property) -> m () -- | For the contentful elements: eg div_. Memonic: bh for branch. -- Duplicate listeners with the same key will be combined, but it is a -- silent error if the same key is used across listeners and props. "If -- an attribute/prop is duplicated the last one defined wins." -- https://www.reactenlightenment.com/react-nodes/4.4.html bh :: (MonadState (DList ReactMarkup) m) => JSRep -> (DList Property) -> m a -> m a -- | Create a MonadState that run the given given a combining function -- where the first arg is the state from running the markup producing -- MonadState with mempty, and the 2nd arg the starting state of the -- resultant MonadState. withMarkup :: MonadState (DList ReactMarkup) m => (DList ReactMarkup -> DList ReactMarkup -> DList ReactMarkup) -> m a -> m a modifyMarkup :: MonadState (DList ReactMarkup) m => (DList ReactMarkup -> DList ReactMarkup) -> m a -> m a overSurfaceProperties :: (DList Property -> DList Property) -> (DList ReactMarkup -> DList ReactMarkup) overAllProperties :: (DList Property -> DList Property) -> (DList ReactMarkup -> DList ReactMarkup) -- | This module based on ReactFluxPropertiesAndEvents.hs. module Glazier.React.NativeEvent.Internal -- | The native event -- https://developer.mozilla.org/en-US/docs/Web/API/Event newtype NativeEvent NativeEvent :: JSRep -> NativeEvent instance Control.DeepSeq.NFData Glazier.React.NativeEvent.Internal.NativeEvent instance Data.String.IsString Glazier.React.NativeEvent.Internal.NativeEvent instance JavaScript.Extras.Cast.ToJS Glazier.React.NativeEvent.Internal.NativeEvent instance GHCJS.Marshal.Internal.PToJSVal Glazier.React.NativeEvent.Internal.NativeEvent instance GHCJS.Internal.Types.IsJSVal Glazier.React.NativeEvent.Internal.NativeEvent instance GHC.Show.Show Glazier.React.NativeEvent.Internal.NativeEvent instance GHC.Generics.Generic Glazier.React.NativeEvent.Internal.NativeEvent instance JavaScript.Extras.Cast.FromJS Glazier.React.NativeEvent.Internal.NativeEvent -- | This module based on ReactFluxPropertiesAndEvents.hs. module Glazier.React.NativeEvent -- | The native event -- https://developer.mozilla.org/en-US/docs/Web/API/Event data NativeEvent module Glazier.React.Notice.Internal -- | Every event in React is a synthetic event, a cross-browser wrapper -- around the native event. which reused from a pool. So it is dangerous -- to keep a reference to a Notice since it may expire and contain -- other things without you knowing. All relevant data from the -- Notice must be consumed as soon you get one. That is, -- Notice must only be used in the first part of -- handleEvent. It is not an instance of NFData and so cannot be -- returned into the second lazy part of handleEvent newtype Notice Notice :: JSRep -> Notice preventDefault :: Notice -> IO () isDefaultPrevented :: Notice -> Bool stopPropagation :: Notice -> IO () isPropagationStopped :: Notice -> Bool -- | Within the strict part of handleEventM the Notice is -- effectively immutable. We want to maintain this lie so that we can -- lazily parse only the properties the event handler is interested in. -- This will throw if J.JSVal is null, or not convertible to the desired -- type so we are assuming that Notice will behave nicely. unsafeGetProperty :: PFromJSVal a => JSVal -> JSString -> a -- | See https://www.w3.org/TR/DOM-Level-3-Events-key/#keys-modifier -- This will throw if J.JSVal is null, but shouldn't happen since we've -- already check for a valid Notice unsafeGetModifierState :: JSVal -> JSString -> Bool instance GHC.Show.Show Glazier.React.Notice.Internal.Notice instance GHC.Generics.Generic Glazier.React.Notice.Internal.Notice instance JavaScript.Extras.Cast.FromJS Glazier.React.Notice.Internal.Notice module Glazier.React.Notice -- | Every event in React is a synthetic event, a cross-browser wrapper -- around the native event. which reused from a pool. So it is dangerous -- to keep a reference to a Notice since it may expire and contain -- other things without you knowing. All relevant data from the -- Notice must be consumed as soon you get one. That is, -- Notice must only be used in the first part of -- handleEvent. It is not an instance of NFData and so cannot be -- returned into the second lazy part of handleEvent data Notice preventDefault :: Notice -> IO () isDefaultPrevented :: Notice -> Bool stopPropagation :: Notice -> IO () isPropagationStopped :: Notice -> Bool -- | This module based on ReactFluxPropertiesAndEvents.hs. module Glazier.React.Event.Synthetic -- | Every Notice can be parsed to an SyntheticEvent. -- SyntheticEvent must only be used in the first part of -- handleEvent. data SyntheticEvent SyntheticEvent :: Bool -> Bool -> EventTarget -> Bool -> Int -> Bool -> NativeEvent -> EventTarget -> Int -> JSString -> SyntheticEvent [bubbles] :: SyntheticEvent -> Bool [cancelable] :: SyntheticEvent -> Bool [currentTarget] :: SyntheticEvent -> EventTarget [defaultPrevented] :: SyntheticEvent -> Bool [eventPhase] :: SyntheticEvent -> Int [isTrusted] :: SyntheticEvent -> Bool [nativeEvent] :: SyntheticEvent -> NativeEvent [target] :: SyntheticEvent -> EventTarget [timeStamp] :: SyntheticEvent -> Int [eventType] :: SyntheticEvent -> JSString -- | We can lie about this not being in IO because within the strict part -- of handleEventM the Notice is effectively immutable. toSyntheticEvent :: Notice -> SyntheticEvent instance GHC.Generics.Generic Glazier.React.Event.Synthetic.SyntheticEvent instance Control.DeepSeq.NFData Glazier.React.Event.Synthetic.SyntheticEvent module Glazier.React.Event.Mouse -- | Mouse and Drag/Drop events MouseEvent must only be used in the -- first part of handleEvent. -- https://facebook.github.io/react/docs/events.html#mouse-events -- https://developer.mozilla.org/en-US/docs/Web/Events Event names -- (eventType) onClick (click) onContextMenu (contextmenu) onDoubleClick -- (dblclick) onDrag (drag) onDragEnd (dragend) onDragEnter (dragenter) -- onDragExit (dragexit) onDragLeave (dragleave) onDragOver (dragover) -- onDragStart (dragstart) onDrop (drop) onMouseDown (mousedown) -- onMouseEnter (mouseenter) onMouseLeave (mouseleave) onMouseMove -- (mousemove) onMouseOut (mouseout) onMouseOver (mouseover) onMouseUp -- (mouseup) data MouseEvent MouseEvent :: Bool -> Int -> Int -> Int -> Int -> Bool -> JSString -> Bool -> Bool -> Int -> Int -> EventTarget -> Int -> Int -> Bool -> MouseEvent [altKey] :: MouseEvent -> Bool [button] :: MouseEvent -> Int [buttons] :: MouseEvent -> Int [clientX] :: MouseEvent -> Int [clientY] :: MouseEvent -> Int [ctrlKey] :: MouseEvent -> Bool [getModifierState] :: MouseEvent -> JSString -> Bool [metaKey] :: MouseEvent -> Bool [pageX] :: MouseEvent -> Int [pageY] :: MouseEvent -> Int [relatedTarget] :: MouseEvent -> EventTarget [screenX] :: MouseEvent -> Int [screenY] :: MouseEvent -> Int [shiftKey] :: MouseEvent -> Bool -- | We can lie about this not being in IO because within the strict part -- of handleEventM the Notice is effectively immutable. toMouseEvent :: Notice -> Maybe MouseEvent instance GHC.Generics.Generic Glazier.React.Event.Mouse.MouseEvent instance Control.DeepSeq.NFData Glazier.React.Event.Mouse.MouseEvent module Glazier.React.Event.Keyboard -- | Keyboard events KeyboardEvent must only be used in the first -- part of handleEvent. -- https://facebook.github.io/react/docs/events.html#keyboard-events -- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent -- Event names (eventType) onKeyDown (keydown) onKeyPress (keypress) -- onKeyUp (keyyp) data KeyboardEvent KeyboardEvent :: Bool -> Int -> Bool -> JSString -> Bool -> JSString -> Int -> JSString -> Int -> Bool -> Bool -> Bool -> Int -> KeyboardEvent [altKey] :: KeyboardEvent -> Bool [charCode] :: KeyboardEvent -> Int [ctrlKey] :: KeyboardEvent -> Bool [getModifierState] :: KeyboardEvent -> JSString -> Bool [key] :: KeyboardEvent -> JSString [keyCode] :: KeyboardEvent -> Int [locale] :: KeyboardEvent -> JSString [location] :: KeyboardEvent -> Int [metaKey] :: KeyboardEvent -> Bool [repeat] :: KeyboardEvent -> Bool [shiftkey] :: KeyboardEvent -> Bool [which] :: KeyboardEvent -> Int -- | We can lie about this not being in IO because within the strict part -- of handleEventM the Notice is effectively immutable. toKeyboardEvent :: Notice -> Maybe KeyboardEvent instance GHC.Generics.Generic Glazier.React.Event.Keyboard.KeyboardEvent instance Control.DeepSeq.NFData Glazier.React.Event.Keyboard.KeyboardEvent module Glazier.React.Event.HashChange data HashChangeEvent HashChangeEvent :: EventTarget -> JSString -> Bool -> Bool -> JSString -> JSString -> HashChangeEvent [target] :: HashChangeEvent -> EventTarget [eventType] :: HashChangeEvent -> JSString [bubbles] :: HashChangeEvent -> Bool [cancelable] :: HashChangeEvent -> Bool [oldURL] :: HashChangeEvent -> JSString [newURL] :: HashChangeEvent -> JSString -- | We can lie about this not being in IO because within the strict part -- of handleEventM the Notice is effectively immutable. toHashChangeEvent :: NativeEvent -> Maybe HashChangeEvent instance GHC.Generics.Generic Glazier.React.Event.HashChange.HashChangeEvent instance Control.DeepSeq.NFData Glazier.React.Event.HashChange.HashChangeEvent -- | Contains commons utilities when defining your own widget module Glazier.React.ReactDOM -- | Using a React Element (first arg) give React rendering control over a -- DOM element (second arg). This should only be called for the topmost -- component. renderDOM :: ReactElement -> JSRep -> IO () module Glazier.React.ReactId.Internal newtype ReactId ReactId :: JSString -> ReactId [unReactId] :: ReactId -> JSString instance GHCJS.Marshal.Internal.PToJSVal Glazier.React.ReactId.Internal.ReactId instance GHCJS.Internal.Types.IsJSVal Glazier.React.ReactId.Internal.ReactId instance Data.String.IsString Glazier.React.ReactId.Internal.ReactId instance JavaScript.Extras.Cast.ToJS Glazier.React.ReactId.Internal.ReactId instance GHC.Classes.Ord Glazier.React.ReactId.Internal.ReactId instance GHC.Classes.Eq Glazier.React.ReactId.Internal.ReactId instance GHC.Show.Show Glazier.React.ReactId.Internal.ReactId instance GHC.Read.Read Glazier.React.ReactId.Internal.ReactId module Glazier.React.ReactId data ReactId module Glazier.React.ReadIORef.Internal -- | NB. Don't export ReadSubject constructor to guarantee that that it -- only contains non-blocking readIORef IO. newtype ReadIORef a ReadIORef :: (IO a) -> ReadIORef a unReadIORef :: ReadIORef a -> IO a doReadIORef :: IORef a -> ReadIORef a instance GHC.Base.Monad Glazier.React.ReadIORef.Internal.ReadIORef instance GHC.Base.Applicative Glazier.React.ReadIORef.Internal.ReadIORef instance GHC.Base.Functor Glazier.React.ReadIORef.Internal.ReadIORef instance GHC.Show.Show (Glazier.React.ReadIORef.Internal.ReadIORef a) instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Glazier.React.ReadIORef.Internal.ReadIORef a) instance GHC.Base.Monoid a => GHC.Base.Monoid (Glazier.React.ReadIORef.Internal.ReadIORef a) module Glazier.React.ReadIORef -- | NB. Don't export ReadSubject constructor to guarantee that that it -- only contains non-blocking readIORef IO. data ReadIORef a unReadIORef :: ReadIORef a -> IO a doReadIORef :: IORef a -> ReadIORef a module Glazier.React.Scene -- | Interactivity for a particular DOM element. data Elemental Elemental :: Maybe EventTarget -> Map JSString (Callback (JSVal -> IO ()), IORef (JSVal -> IO (), IO ())) -> Elemental [$sel:elementalRef:Elemental] :: Elemental -> Maybe EventTarget [$sel:reactListeners:Elemental] :: Elemental -> Map JSString (Callback (JSVal -> IO ()), IORef (JSVal -> IO (), IO ())) _reactListeners :: Lens' Elemental (Map JSString (Callback (JSVal -> IO ()), IORef (JSVal -> IO (), IO ()))) _elementalRef :: Lens' Elemental (Maybe EventTarget) data ShimCallbacks ShimCallbacks :: Callback (IO JSVal) -> Callback (IO ()) -> Callback (IO ()) -> Callback (JSVal -> IO ()) -> ShimCallbacks [$sel:shimRender:ShimCallbacks] :: ShimCallbacks -> Callback (IO JSVal) [$sel:shimMounted:ShimCallbacks] :: ShimCallbacks -> Callback (IO ()) [$sel:shimRendered:ShimCallbacks] :: ShimCallbacks -> Callback (IO ()) [$sel:shimRef:ShimCallbacks] :: ShimCallbacks -> Callback (JSVal -> IO ()) _shimRendered :: Lens' ShimCallbacks (Callback (IO ())) _shimRender :: Lens' ShimCallbacks (Callback (IO JSVal)) _shimRef :: Lens' ShimCallbacks (Callback (JSVal -> IO ())) _shimMounted :: Lens' ShimCallbacks (Callback (IO ())) -- | Interactivity data for a react component data Plan Plan :: ReactId -> Maybe ComponentRef -> ShimCallbacks -> IO () -> IO () -> IO () -> IO () -> Map ReactId Elemental -> Map ReactId (Callback (JSVal -> IO ()), IORef (JSVal -> IO (), IO ())) -> IO () -> Bool -> Bool -> Plan [$sel:planId:Plan] :: Plan -> ReactId [$sel:componentRef:Plan] :: Plan -> Maybe ComponentRef [$sel:shimCallbacks:Plan] :: Plan -> ShimCallbacks [$sel:tickedListener:Plan] :: Plan -> IO () [$sel:renderedListener:Plan] :: Plan -> IO () [$sel:mountedListener:Plan] :: Plan -> IO () [$sel:nextRenderedListener:Plan] :: Plan -> IO () [$sel:elementals:Plan] :: Plan -> Map ReactId Elemental [$sel:domlListeners:Plan] :: Plan -> Map ReactId (Callback (JSVal -> IO ()), IORef (JSVal -> IO (), IO ())) [$sel:finalCleanup:Plan] :: Plan -> IO () [$sel:tickedNotified:Plan] :: Plan -> Bool [$sel:rerenderRequired:Plan] :: Plan -> Bool _tickedNotified :: Lens' Plan Bool _tickedListener :: Lens' Plan (IO ()) _shimCallbacks :: Lens' Plan ShimCallbacks _rerenderRequired :: Lens' Plan Bool _renderedListener :: Lens' Plan (IO ()) _planId :: Lens' Plan ReactId _nextRenderedListener :: Lens' Plan (IO ()) _mountedListener :: Lens' Plan (IO ()) _finalCleanup :: Lens' Plan (IO ()) _elementals :: Lens' Plan (Map ReactId Elemental) _domlListeners :: Lens' Plan (Map ReactId (Callback (JSVal -> IO ()), IORef (JSVal -> IO (), IO ()))) _componentRef :: Lens' Plan (Maybe ComponentRef) -- | A Scene contains interactivity data for all widgets as well as -- the model data. data Scene s Scene :: Plan -> s -> Scene s [$sel:plan:Scene] :: Scene s -> Plan [$sel:model:Scene] :: Scene s -> s _model :: Lens (Scene s) (Scene s') s s' _plan :: Lens' (Scene s) Plan editSceneModel :: (Functor f) => LensLike' f s a -> LensLike' f (Scene s) (Scene a) magnifiedScene :: (Magnify m n (Scene a) (Scene b), Functor (Magnified m r)) => LensLike' (Magnified m r) b a -> m r -> n r zoomedScene :: (Zoom m n (Scene a) (Scene b), Functor (Zoomed m r)) => LensLike' (Zoomed m r) b a -> m r -> n r elementTarget :: ReactId -> Traversal' (Scene s) EventTarget instance GHC.Base.Functor Glazier.React.Scene.Scene instance GHC.Show.Show s => GHC.Show.Show (Glazier.React.Scene.Scene s) instance GHC.Generics.Generic (Glazier.React.Scene.Scene s) instance GHC.Show.Show Glazier.React.Scene.Plan instance GHC.Generics.Generic Glazier.React.Scene.Plan instance GHC.Generics.Generic Glazier.React.Scene.ShimCallbacks instance GHC.Generics.Generic Glazier.React.Scene.Elemental module Glazier.React.Subject.Internal -- | Using MVar for synchronizing because it guarantees FIFO wakeup which -- will help prevent old updates overriding new updates. The constructor -- is hidden to maintain the expectation that the last two member will -- keep the ShimCallbacks inside the Scene alive. Before -- removing Subject from a container, use prolong to store the -- prolonging IO action "nextRenderedListener" action handler, so that -- the ShimCallbacks is garbage collected only after the child -- widget is no longer rendered. data Subject p Subject :: (IORef (Scene p)) -> (MVar (Scene p)) -> (IORef (MVar ())) -> (MVar ()) -> Subject p sceneRef :: Subject p -> IORef (Scene p) sceneVar :: Subject p -> MVar (Scene p) renderLeaseRef :: Subject p -> IORef (MVar ()) otherLeaseVar :: Subject p -> MVar () -- | Creates an IO action whose existence will keep the lease alive. -- Running it has no side effects. prolong :: Subject s -> IO () instance GHC.Classes.Eq (Glazier.React.Subject.Internal.Subject p) module Glazier.React.Subject -- | Using MVar for synchronizing because it guarantees FIFO wakeup which -- will help prevent old updates overriding new updates. The constructor -- is hidden to maintain the expectation that the last two member will -- keep the ShimCallbacks inside the Scene alive. Before -- removing Subject from a container, use prolong to store the -- prolonging IO action "nextRenderedListener" action handler, so that -- the ShimCallbacks is garbage collected only after the child -- widget is no longer rendered. data Subject p sceneRef :: Subject p -> IORef (Scene p) sceneVar :: Subject p -> MVar (Scene p) -- | Creates an IO action whose existence will keep the lease alive. -- Running it has no side effects. prolong :: Subject s -> IO () module Glazier.React.Entity data Entity p s Entity :: (Subject p) -> (Traversal' p s) -> Entity p s _subject :: Lens' (Entity p s) (Subject p) _self :: Lens (Entity p s) (Entity p s') (ReifiedTraversal' p s) (ReifiedTraversal' p s') magnifiedEntity :: (Magnify m n (Entity p a) (Entity p b), Contravariant (Magnified m r)) => Traversal' b a -> m r -> n r module Glazier.React.Gadget -- | The s state can be magnified with magnifiedEntity type Gadget cmd p s = ReaderT (Entity p s) (ContT () (State (DList cmd))) toGadget :: (Entity p s -> (a -> State (DList cmd) ()) -> State (DList cmd) ()) -> Gadget cmd p s a runGadget :: Gadget cmd p s a -> Entity p s -> (a -> State (DList cmd) ()) -> State (DList cmd) () gadgetWith :: Subject s -> Gadget cmd s s a -> ContT () (State (DList cmd)) a evalGadget :: Gadget cmd p s () -> Entity p s -> State (DList cmd) () module Glazier.React.Window type Window s = RWST (Scene s) () (DList ReactMarkup) ReadIORef getListeners :: MonadReader (Scene s) m => ReactId -> m [Property] -- | Interactive version of lf using listeners obtained from the -- Plan for a ElementalId. lf' :: (MonadReader (Scene s) m, MonadState (DList ReactMarkup) m) => ReactId -> JSRep -> DList Property -> m () -- | Interactive version of bh bh' :: (MonadReader (Scene s) m, MonadState (DList ReactMarkup) m) => ReactId -> JSRep -> DList Property -> m r -> m r bindListenerContext :: JSRep -> Callback (JSVal -> JSVal -> IO ()) -> JSRep displaySubject :: (MonadTrans t, MonadState (DList ReactMarkup) (t ReadIORef)) => Subject s -> t ReadIORef () js_bindListenerContext :: JSRep -> Callback (JSVal -> JSVal -> IO ()) -> JSRep module Glazier.React.Widget -- | A Widget is a Gadget that fires Either a -- Window or a value. type Widget cmd p s a = ExceptT (Window s ()) (Gadget cmd p s) a -- | Use this function to verify at compile time that the first widget -- doesn't require any AsFacet (IO cmd) cmd. noIOWidget :: Widget (NoIOCmd cmd) s s a -> Widget cmd s s a -> Widget cmd s s a magnifyWidget :: Traversal' t s -> ExceptT (Window s ()) (Gadget cmd p s) a -> ExceptT (Window t ()) (Gadget cmd p t) a -- | Convert a Gadget into a Widget widget :: Gadget cmd p s (Either (Window s ()) a) -> Widget cmd p s a runWidget :: Widget cmd p s a -> Gadget cmd p s (Either (Window s ()) a) mapWidget :: (Gadget cmd p s (Either (Window s ()) a) -> Gadget cmd p' s' (Either (Window s' ()) b)) -> Widget cmd p s a -> Widget cmd p' s' b display :: Window s () -> Widget cmd p s a overWindow :: (Window s () -> Window s ()) -> Widget cmd p s a -> Widget cmd p s a overWindow2 :: (Window s () -> Window s () -> Window s ()) -> Widget cmd p s a -> Widget cmd p s a -> Widget cmd p s a overWindow3 :: (Window s () -> Window s () -> Window s () -> Window s ()) -> Widget cmd p s a -> Widget cmd p s a -> Widget cmd p s a -> Widget cmd p s a overWindow2' :: (ChooseBoth x1 x2 ys) => (Window s () -> Window s () -> Window s ()) -> Widget cmd p s (Which x1) -> Widget cmd p s (Which x2) -> Widget cmd p s (Which ys) overWindow3' :: (Diversify x1 ys, Diversify x2 ys, Diversify x3 ys, ys ~ AppendUnique x1 (AppendUnique x2 x3)) => (Window s () -> Window s () -> Window s () -> Window s ()) -> Widget cmd p s (Which x1) -> Widget cmd p s (Which x2) -> Widget cmd p s (Which x3) -> Widget cmd p s (Which ys) withWindow :: Widget cmd p s a -> (Window s () -> Widget cmd p s a) -> Widget cmd p s a withWindow' :: (ChooseBoth xs ys zs) => Widget cmd p s (Which xs) -> (Window s () -> Widget cmd p s (Which ys)) -> Widget cmd p s (Which zs) module Glazier.React.Reactor type AsReactor cmd = (AsFacet [cmd] cmd, AsFacet (ReactorCmd cmd) cmd) type MonadReactor p s cmd m = (AsReactor cmd, MonadReader (Entity p s) m, MonadCommand cmd m) -- | NB. ReactorCmd is not a functor because of the Widget -- cmd in MkSubject data ReactorCmd cmd -- | Make a unique named id [MkReactId] :: JSString -> (ReactId -> cmd) -> ReactorCmd cmd -- | the the rendering function in a Subject, replace any existing render -- callback [SetRender] :: Subject s -> Window s () -> ReactorCmd cmd -- | Make a fully initialized subject (with ShimCallbacks) from a widget -- spec and state [MkSubject] :: Widget cmd s s () -> s -> (Subject s -> cmd) -> ReactorCmd cmd -- | Keep subject alive until the next rerender [BookSubjectCleanup] :: Subject s -> ReactorCmd cmd -- | Generate a list of commands from reading the model. [GetModel] :: Subject s -> (s -> cmd) -> ReactorCmd cmd [GetElementalRef] :: Subject s -> ReactId -> (EventTarget -> cmd) -> ReactorCmd cmd -- | Rerender a ShimComponent using the given state. [Rerender] :: Subject s -> ReactorCmd cmd -- | Update and rerender. [TickModel] :: Subject s -> ModelState s cmd -> ReactorCmd cmd -- | Create and register a dom callback [RegisterDOMListener] :: NFData a => Subject s -> JSRep -> JSString -> (JSRep -> MaybeT IO a) -> (a -> cmd) -> ReactorCmd cmd -- | Create and register a react callback If the callback is for "ref", -- then an listener to update elementalRef for -- GetEventTarget will automatically be added just before the -- listener in RegisterReactListener. [RegisterReactListener] :: NFData a => Subject s -> ReactId -> JSString -> (JSRep -> MaybeT IO a) -> (a -> cmd) -> ReactorCmd cmd -- | Create and register a callback for the mounted event [RegisterMountedListener] :: Subject s -> cmd -> ReactorCmd cmd -- | Create and register a callback for the rendered event [RegisterRenderedListener] :: Subject s -> cmd -> ReactorCmd cmd -- | Create and register a callback for the rendered event [RegisterNextRenderedListener] :: Subject s -> cmd -> ReactorCmd cmd -- | Create and register a callback for the state updated event [RegisterTickedListener] :: Subject s -> cmd -> ReactorCmd cmd type ModelState s = StateT s ReadIORef -- | Make a unique named id mkReactId :: (AsReactor cmd, MonadCommand cmd m) => JSString -> m ReactId setRender :: (AsReactor cmd, MonadCommand cmd m) => Subject s -> Window s () -> m () -- | Make an initialized Subject for a given model using the given -- Widget. mkSubject :: (AsReactor cmd, MonadCommand cmd m) => Widget cmd s s a -> s -> m (Either a (Subject s)) -- | Make an initialized Subject for a given model using the given -- Widget. mkSubject' :: (AsReactor cmd, MonadCommand cmd m) => Widget cmd s s () -> s -> m (Subject s) -- | Make an initialized Subject for a given model using the given -- Widget. withMkSubject :: (AsReactor cmd, MonadCommand cmd m) => Widget cmd s s a -> s -> (Subject s -> m ()) -> m a -- | Schedule cleanup of the callbacks when the parent widget is -- rerendered. bookSubjectCleanup :: (MonadReactor p allS cmd m) => Subject s -> m () -- | Get the Model and exec actions, using the current -- Entity context getModel :: (MonadReactor p s cmd m) => m s -- | Get the event target If a "ref" callback to update -- elementalRef has not been added; then add it, rerender, then -- return the EventTarget. getElementalRef :: (MonadReactor p s cmd m) => ReactId -> m EventTarget -- | Rerender the ShimComponent using the current Entity context rerender :: (MonadReactor p s cmd m) => m () -- | Update the Model using the current Entity context tickModel :: (MonadReactor p s cmd m) => ModelState s () -> m () -- | Update the Scene using the current Entity context, -- and also return the next action to execute. tickModelThen :: (Also m a, MonadReactor p s cmd m) => ModelState s (m a) -> m a -- | Create a callback for a JSRep and add it to this elementals's -- dlist of listeners. domTrigger :: (NFData a, MonadReactor p s cmd m) => JSRep -> JSString -> (JSRep -> MaybeT IO a) -> m a -- | A variation of trigger which ignores the event but fires the given arg -- instead. domTrigger_ :: (MonadReactor p s cmd m) => JSRep -> JSString -> a -> m a -- | Create a callback for a Notice and add it to this elementals's -- dlist of listeners. trigger :: (NFData a, MonadReactor p s cmd m) => ReactId -> JSString -> (Notice -> MaybeT IO a) -> m a -- | A variation of trigger which ignores the event but fires the given arg -- instead. trigger_ :: (MonadReactor p s cmd m) => ReactId -> JSString -> a -> m a -- | Register actions to execute after a render. It is safe to -- postCmd' a TickScene or Rerender. These -- command will not trigger another rendered event. -- -- NB. This is trigged by react componentDidMount See -- jsbits/react.js hgr$shimComponent. These callbacks are called after -- the ref callback by React See -- https://reactjs.org/docs/refs-and-the-dom.html. onMounted :: MonadReactor p s cmd m => m a -> m a -- | Register actions to execute after a render. It is safe to -- postCmd' a TickScene or Rerender. These -- command will not trigger another rendered event. -- -- NB. This is trigged by react componentDidUpdate and -- componentDidMount so it is also called for the initial -- render. See jsbits/react.js hgr$shimComponent. These callbacks are -- called after the ref callback by React See -- https://reactjs.org/docs/refs-and-the-dom.html. onRendered :: MonadReactor p s cmd m => m a -> m a onNextRendered :: MonadReactor p s cmd m => m a -> m a -- | Register actions to execute after the state has been updated with -- TickState. It is safe to postCmd' another TickScene, -- another onRendered event will not be generated. -- -- NB. This is trigged by react componentDidUpdate and -- componentDidMount so it is also called for the initial -- render. See jsbits/react.js hgr$shimComponent. These callbacks are -- called after the ref callback by React See -- https://reactjs.org/docs/refs-and-the-dom.html. onTicked :: MonadReactor p s cmd m => m a -> m a instance GHC.Show.Show (Glazier.React.Reactor.ReactorCmd cmd) module Glazier.React.Reactor.Exec data ReactorEnv ReactorEnv :: MVar Int -> TQueue (IO (IO ())) -> ReactorEnv [reactIdEnv] :: ReactorEnv -> MVar Int [reactorBackgroundEnv] :: ReactorEnv -> TQueue (IO (IO ())) mkReactorEnvIO :: IO (ReactorEnv) -- | An example of starting an app using the glazier-react framework startApp :: (MonadIO m, MonadReader r m, Has ReactorEnv r, Typeable s, AsReactor cmd, AsFacet (IO cmd) cmd) => (cmd -> m ()) -> Widget cmd s s () -> s -> JSRep -> m () reactorBackgroundWork :: TQueue (IO (IO ())) -> IO () execReactorCmd :: (MonadUnliftIO m, MonadReader r m, AsReactor cmd, Has ReactorEnv r) => (cmd -> m ()) -> ReactorCmd cmd -> m () execMkReactId :: (MonadIO m, Has ReactorEnv r, MonadReader r m) => JSString -> m ReactId execSetRender :: MonadIO m => Subject s -> Window s () -> m () -- | Make an initialized Subject for a given model using the given -- Window rendering function. The original window should be -- dropped and the Widget reduced to just a Gadget to -- emphasis the fact that the Window was used up. -- displaySubject should be used to render the subject. execMkSubject :: (MonadIO m, AsReactor cmd, Has ReactorEnv r, MonadReader r m) => (cmd -> m ()) -> Widget cmd s s () -> s -> m (Subject s) execBookSubjectCleanup :: (MonadIO m, MonadReader r m, Has ReactorEnv r) => Subject s -> m () execGetModel :: MonadIO m => Subject s -> m s execGetElementalRef :: (MonadUnliftIO m, MonadReader r m, Has ReactorEnv r) => (cmd -> m ()) -> Subject s -> ReactId -> (EventTarget -> cmd) -> m () execRerender :: (MonadIO m, MonadReader r m, Has ReactorEnv r) => Subject s -> m () -- | No need to run in a separate thread because it should never block for -- a significant amount of time. Update the scene MVar with the -- given action. Also triggers a rerender. execTickModel :: (MonadIO m, MonadReader r m, Has ReactorEnv r) => Subject s -> ModelState s cmd -> m cmd execRegisterDOMListener :: (NFData a, MonadUnliftIO m, Has ReactorEnv r, MonadReader r m) => (cmd -> m ()) -> Subject s -> JSRep -> JSString -> (JSRep -> MaybeT IO a) -> (a -> cmd) -> m () execRegisterReactListener :: (NFData a, MonadUnliftIO m) => (cmd -> m ()) -> Subject s -> ReactId -> JSString -> (JSRep -> MaybeT IO a) -> (a -> cmd) -> m () execRegisterMountedListener :: (MonadUnliftIO m) => (cmd -> m ()) -> Subject s -> cmd -> m () execRegisterRenderedListener :: (MonadUnliftIO m) => (cmd -> m ()) -> Subject s -> cmd -> m () execRegisterNextRenderedListener :: (MonadUnliftIO m) => (cmd -> m ()) -> Subject s -> cmd -> m () execRegisterTickedListener :: (MonadUnliftIO m) => (cmd -> m ()) -> Subject s -> cmd -> m () -- | NB. Glazier.React.Event.* are not exported due to duplicate record -- fields It is up to the user to import the Event modules as required. module Glazier.React