<commit_before>module Nauva.Service.Router
    ( RouterH(..)
    , Location(..)
    ) where


import Data.Text (Text)
import Control.Concurrent.STM



data RouterH = RouterH
    { hLocation :: (TVar Location, TChan Location)
      -- ^ The current 'Location' and a (broadcast) 'TChan' which can
      -- be subscribed to in order to receive notifications when the location
      -- changes.

    , hPush :: Text -> IO ()
      -- ^ Push a new URL to the router stack.
    }


data Location = Location
    { locPathname :: !Text
    }
<commit_msg>link: higher-order element for creating router links<commit_after>{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}

module Nauva.Service.Router
    ( RouterH(..)
    , Location(..)

    , LinkProps(..)
    , link
    ) where


import           Data.Text  (Text)
import qualified Data.Aeson as A

import           Control.Concurrent.STM

import           Nauva.Internal.Types
import           Nauva.Internal.Events
import           Nauva.View
import           Nauva.NJS



data RouterH = RouterH
    { hLocation :: (TVar Location, TChan Location)
      -- ^ The current 'Location' and a (broadcast) 'TChan' which can
      -- be subscribed to in order to receive notifications when the location
      -- changes.

    , hPush :: Text -> IO ()
      -- ^ Push a new URL to the router stack.
    }


data Location = Location
    { locPathname :: !Text
    }



-------------------------------------------------------------------------------
-- link

data LinkProps = LinkProps
    { routerH :: !RouterH
      -- ^ The router handle provides the callbacks.
    , href :: !Text
      -- ^ The path which shall be pushed to the router history when the element
      -- is clicked.
    , element :: !Element
      -- ^ The element to which a 'onClick' handler is attached.
    }

link :: LinkProps -> Element
link = component_ linkComponent



linkComponent :: Component LinkProps () LinkProps ()
linkComponent = Component
    { componentId = mkComponentId
    , componentDisplayName = "Link"
    , initialComponentState = \props -> pure (props, [])
    , componentEventListeners = \_ -> []
    , componentHooks = emptyHooks
    , processLifecycleEvent = \() s -> (s, [])
    , receiveProps = \props _ -> pure (props, [], [])
    , update = \() s -> (s, [clickEffect s])
    , renderComponent = \(LinkProps {..}) -> with element [onClick_ onClickHandler]
    , componentSnapshot = \_ -> A.object []
    , restoreComponent = \_ s -> Right (s, [])
    }
  where
    onClickHandler :: F1 MouseEvent (EventHandler ())
    onClickHandler = eventHandler $ \ev -> do
        preventDefault
        action $ value0E $ njsCon0 "()" ()

    clickEffect :: LinkProps -> IO (Maybe ())
    clickEffect (LinkProps {..}) = do
        hPush routerH href
        pure Nothing

{'fraction_non_alphanumeric': 0.14118481731110322, 'fraction_numerical': 0.001064207165661582, 'mean_word_length': 2.1333333333333333, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4541647', 'n_tokens_mistral': 825, 'n_tokens_neox': 798, 'n_words': 248}