Skip to content

Commit

Permalink
Add an example of remote widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
ajnsit committed May 2, 2024
1 parent 93d991f commit e3ff504
Show file tree
Hide file tree
Showing 13 changed files with 51 additions and 4,455 deletions.
65 changes: 51 additions & 14 deletions examples/src/Test/Calc.purs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ module Test.Calc where
import Prelude

import Concur.Core (Widget)
import Concur.Core.Patterns (remoteWidget)
import Concur.React (HTML)
import Concur.React.DOM (button, text, table', tr', td', tbody')
import Concur.React.Props (onClick)
import Concur.React.DOM as D
import Concur.React.Props as P
import Control.Alt ((<|>))
import Control.Monad.Rec.Class (forever)
import Control.MultiAlternative (orr)
import Data.List (List(..), uncons, (:))
import Data.Maybe (Maybe(..))
Expand All @@ -16,11 +19,11 @@ data CalculatorAction = Plus | Minus | Times | Div | Enter | Clear | Digit Int

-- Button pad widget
calcButtonsWidget :: Widget HTML CalculatorAction
calcButtonsWidget = table' $ pure $ tbody' $
[ tr' [d 7, d 8, d 9, opDiv]
, tr' [d 4, d 5, d 6, opTimes]
, tr' [d 1, d 2, d 3, opMinus]
, tr' [d 0, ent, cls, opPlus]
calcButtonsWidget = D.table' $ pure $ D.tbody' $
[ D.tr' [d 7, d 8, d 9, opDiv]
, D.tr' [d 4, d 5, d 6, opTimes]
, D.tr' [d 1, d 2, d 3, opMinus]
, D.tr' [d 0, ent, cls, opPlus]
]
where
d n = but (Digit n) (show n)
Expand All @@ -30,7 +33,7 @@ calcButtonsWidget = table' $ pure $ tbody' $
opTimes = but Times "*"
opMinus = but Minus "-"
opPlus = but Plus "+"
but x s = x <$ td' [button [onClick] [text s]]
but x s = x <$ D.td' [D.button [P.onClick] [D.text s]]

-- Postfix calculation
calc :: List Int -> CalculatorAction -> Tuple (List Int) Int
Expand All @@ -50,11 +53,45 @@ calc arr axn = case uncons arr, axn of
err = Tuple arr 0
new n s = Tuple (n:s) n

-- Put everything together
-- We create a display widget that wires everything up
-- It renders the buttons and display in parallel
-- And then handles button input, performs the calculation, and recurses
calcDisplay :: forall a. List Int -> Widget HTML CalculatorAction -> Widget HTML CalculatorAction -> Widget HTML a
calcDisplay st display buttons = do
a <- display <|> buttons
let Tuple st' n = calc st a
calcDisplay st' (D.text (show n)) buttons

-- Using calcDisplay is pretty easy as can be seen in `calcWidgetStandard`
calcWidgetStandard :: forall a. Widget HTML a
calcWidgetStandard = calcDisplay Nil defaultDisplay calcButtonsWidget
where
defaultDisplay = D.text "Press a button"

-- But in this example we don't use this "standard" way of doing things

-- Instead, we show off remote widgets to drive the display
-- This code may seem longer, but it's *sometimes* cleaner to use "action at a distance".
-- It's also very useful to avoid having to rework complex logic.

-- For example, what if want the buttons to render in a different place, and not right next to the display?
-- By passing the Buttons widget off to calc, we cede control of where it is rendered
-- But remote widgets can help us recover that control
calcWidget :: forall a. Widget HTML a
calcWidget = go 0 Nil
calcWidget = do
-- First create a remote widget for the buttons
remoteButtons <- remoteWidget calcButtonsWidget
orr
-- Then we pass only the yield part of the remote buttons to calcDisplay
[ calcDisplay Nil defaultDisplay remoteButtons.yield
-- Meanwhile we render the buttons in a potentially different place
-- Let's give the buttons a subtle background
, D.div [ P.style {background: "beige", width: "fit-content"} ]
-- Note we don't care WHERE or HOW the events from the buttons are being handled
-- We only have to forever keep emmitting events
-- It's a never ending widget that can get information out!
[ forever remoteButtons.render ]
]
where
go n s = do
a <- orr [text (show n), calcButtonsWidget]
let Tuple s' n' = calc s a
go n' s'
defaultDisplay = D.text "This display is controlled by other widgets. GO AHEAD. PRESS A BUTTON."

25 changes: 0 additions & 25 deletions stark/spago.dhall

This file was deleted.

9 changes: 0 additions & 9 deletions stark/src/Concur/Stark.purs

This file was deleted.

Loading

0 comments on commit e3ff504

Please sign in to comment.