{"id":22258078,"url":"https://github.com/coot/purescript-react-spaces","last_synced_at":"2025-04-11T17:22:32.506Z","repository":{"id":58225566,"uuid":"98565178","full_name":"coot/purescript-react-spaces","owner":"coot","description":"Combinator library for generating React markup.","archived":false,"fork":false,"pushed_at":"2017-11-01T20:34:42.000Z","size":342,"stargazers_count":8,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T13:13:19.839Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PureScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-27T17:48:28.000Z","updated_at":"2019-04-13T15:35:33.000Z","dependencies_parsed_at":"2022-09-14T13:51:45.986Z","dependency_job_id":null,"html_url":"https://github.com/coot/purescript-react-spaces","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coot%2Fpurescript-react-spaces","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coot%2Fpurescript-react-spaces/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coot%2Fpurescript-react-spaces/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coot%2Fpurescript-react-spaces/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coot","download_url":"https://codeload.github.com/coot/purescript-react-spaces/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248447964,"owners_count":21105210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-03T08:13:24.802Z","updated_at":"2025-04-11T17:22:32.483Z","avatar_url":"https://github.com/coot.png","language":"PureScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# purescript-react-spaces\n**Combinator library for writing React vDOM**\n\n[![Maintainer: coot](https://img.shields.io/badge/maintainer-coot-lightgrey.svg)](http://github.com/coot)\n[![Documentation](https://pursuit.purescript.org/packages/purescript-react-spaces/badge)](https://pursuit.purescript.org/packages/purescript-react-spaces)\n[![Build Status](https://travis-ci.org/coot/purescript-react-spaces.svg?branch=master)](https://travis-ci.org/coot/purescript-react-spaces)\n\nIt it is heavily inspired by [purescript-smolder](https://github.com/bodil/purescript-smolder).\n\n# Usage\nThe top level module exports\n\n```purescript\nrenderIn\n  :: (Array ReactElement -\u003e ReactElement)\n  -\u003e SpaceM\n  -\u003e ReactElement\n\nrender\n  :: SpaceM\n  -\u003e Array ReactElement\n```\n\nwhich you can chain with `render` method of your spec:\n```purescript\ns :: ReactSpec Unit Unit\ns = spec unit (map (renderIn React.DOM.div') \u003c\u003c\u003c render)\n  where\n    render :: ReactThis Unit Unit -\u003e SpaceM\n    render this = pure $\n      div !. \"greeting\" $ do\n\ttext \"Hello World!\n\n```\n\n# Example\n\nRun\n```sh\nnpm run example:build\nnpm run example:serve\n```\n\n\nIt will compile the following simple example:\n```purescript\ngreeting\n  :: forall eff\n   . ReactClass\n      (Greeting\n\t( props :: ReactProps\n\t, refs :: ReactRefs ReadOnly\n\t, state :: ReactState ReadWrite\n\t| eff))\ngreeting = createClassStateless'\n  \\(Greeting { name, onChange }) chldrn\n  -\u003e renderIn React.DOM.div' do\n    div !. \"greeting\" $ do\n      label do\n\tdiv do\n\t  h1 do\n\t    elements chldrn\n\t    text \" \"\n\t    text name\n\t    text if not (S.null name) then \"!\" else \"\"\n\t-- note that you don't need to pass `empty` to `input`\n\tinput ! P.value name ! P.onChange (handleChange onChange)\n\n  where \n    handleChange onChange ev = do\n      v \u003c- pure (unsafeCoerce ev).target.value\n      onChange v\n\nnewtype Counter eff = Counter\n  { counter :: Int\n  , onClick :: Eff eff Unit\n  }\ncounter\n  :: forall eff\n   . ReactClass\n      (Counter\n\t( props :: ReactProps\n\t, refs :: ReactRefs ReadOnly\n\t, state :: ReactState ReadWrite\n\t| eff))\ncounter = createClassStateless'\n  (\\(Counter { counter: c, onClick: onClick' }) chldrn\n  -\u003e renderIn React.DOM.div' do\n    div do\n      elements chldrn\n      span $ text (show c)\n      button ! onClick (handleClick onClick') $ do\n\ttext \"count\")\n\n  where\n    handleClick onClick ev = onClick\n\nbase :: ReactClass Unit\nbase = createClass (spc { displayName = \"BaseClass\" })\n  where\n    spc = spec { name: \"John\", counter: 0 }\n      (map (renderIn React.DOM.div') \u003c\u003c\u003c renderFn)\n\n    handleName this name = do\n      transformState this (_ { name = name })\n\n    handleCounter this = do\n      transformState this (\\st@{counter} -\u003e st { counter = (counter + 1) })\n\n    renderFn this = do\n      { counter, name } \u003c- readState this\n      pure $ do\n\tgreeting ^^ (Greeting { name, onChange: handleName this })\n\t  $ do\n\t    span $ text \"Hello\"\n        counter ^^ (Counter { counter, onClick: handleCounter this })\n\t  $ do\n\t    h1 $ \"Count on the sea...\"\n```\n\n# Rendering using `sequence_`\n\nOften in `React` you want to render a node which is present under some\ncondition.  You might have a `Maybe String` in your props that you'd like to\nshow only if you have a `Just` value.  Since `SpaceM` is an instance of\n`Foldable` type class you can do that in this way:\n```\nnCls :: ReactClass { name :: String }\nnCls = createClassStateless \\{ name } -\u003e renderIn React.DOM.div' do\n  h1 !. \"title\" $ do\n    text \"Hello \"\n    span !. \"name\" $ text name\n\nmSpec :: forall eff. ReactSpec { mName :: Maybe String } Unit eff\nmSpec = spec unit renderFn\n  where\n    renderFn this = do\n      { mName } \u003c- getProps this\n      let mNameNode = (nCls ^ _) \u003c$\u003e mName\n      pure $ renderIn React.DOM.div' $ do\n\th1 !. \"app\" $ do\n\t  text \"Hello App\"\n\tsequence_ mNameNode\n```\nCheckout [examples](https://github.com/coot/purescript-react-spaces/blob/master/examples/src/Echo.purs#L73) for a `echoApp` component.\n\nFor another example you can check out\n[purescript-isomorphic-react-example](https://github.com/coot/purescript-isomorphic-react-example/blob/master/src/Jam/App.purs#L249).\n\n# Conditional rendering using `with`\n\nAnother common pattern is to conditionally include part of a ui.  You can use `when` for that:\n```\n  renderIn React.DOM.div' $ do\n    h1 $ title \"Hello\"\n    when condition do\n      -- note that `React.Space.DOM.input` elements do not accept children (unlike `React.DOM.input`)\n      input ! P.onChange (handleChange this)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoot%2Fpurescript-react-spaces","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoot%2Fpurescript-react-spaces","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoot%2Fpurescript-react-spaces/lists"}