module Gargantext.Utils.Reactix where import Prelude import DOM.Simple.Event as DE import Data.Maybe (Maybe(..)) import Data.Nullable (Nullable, null, toMaybe) import Data.Traversable (traverse_) import Data.Tuple (Tuple(..)) import Data.Tuple.Nested ((/\)) import Effect (Effect) import Effect.Uncurried (EffectFn1, mkEffectFn1) import FFI.Simple ((...), defineProperty) import React (ReactClass, ReactElement, Children, class IsReactElement, class ReactPropFields) import React as React import Reactix as R import Reactix.DOM.HTML (ElemFactory) import Reactix.React (createDOMElement) import Reactix.SyntheticEvent as RE import Thermite (Spec, simpleSpec, Render, defaultPerformAction) import Unsafe.Coerce (unsafeCoerce) newtype Point = Point { x :: Number, y :: Number } -- | Turns a ReactElement into aReactix Element -- | buff (v.) to polish buff :: ReactElement -> R.Element buff = unsafeCoerce -- | Turns a Reactix Element into a ReactElement. -- | scuff (v.) to spoil the gloss or finish of. scuff :: R.Element -> ReactElement scuff = unsafeCoerce class ToElement a where toElement :: a -> R.Element instance toElementElement :: ToElement R.Element where toElement = identity instance toElementReactElement :: ToElement ReactElement where toElement = buff instance toElementArray :: ToElement a => ToElement (Array a) where toElement = R.fragment <<< map toElement {- instance isReactElementElement :: IsReactElement R.Element where toElement = scuff -} elSpec :: forall component props . R.IsComponent component props (Array R.Element) => component -> Spec {} (Record props) Void elSpec cpt = simpleSpec defaultPerformAction render where render :: Render {} (Record props) Void render _ props _ children = [scuff $ R.createElement cpt props (buff <$> children)] createElement' :: forall required given . ReactPropFields required given => ReactClass { children :: Children | required } -> Record given -> Array R.Element -> R.Element createElement' reactClass props children = buff $ React.createElement reactClass props $ scuff <$> children {- instance isComponentReactClass :: R.IsComponent (ReactClass { children :: Children | props }) props (Array R.Element) where createElement reactClass props children = React.createElement reactClass props children -} mousePosition :: RE.SyntheticEvent DE.MouseEvent -> Point mousePosition e = Point { x: RE.clientX e, y: RE.clientY e } -- | This is naughty, it quietly mutates the input and returns it named :: forall o. String -> o -> o named = flip $ defineProperty "name" overState :: forall t. (t -> t) -> R.State t -> Effect Unit overState f (_state /\ setState) = setState f select :: ElemFactory select = createDOMElement "select" effToggler :: forall e. R.State Boolean -> EffectFn1 e Unit effToggler (value /\ setValue) = mkEffectFn1 $ \e -> setValue $ const $ not value unsafeEventValue :: forall event. event -> String unsafeEventValue e = (unsafeCoerce e).target.value