Package

purescript-react-basic-dom-beta

Repository
rowtype-yoga/purescript-react-basic-dom-beta
License
WTFPL
Uploaded by
pacchettibotti
Published on
2024-10-04T14:07:26Z

Want to help out? Checkout CONTRIBUTING.md

After using react-basic-hooks for a while I've gathered a small wishlist for things that I'd like to work a little differently.

What it looks like:

module Example where

import Prelude hiding (div)
import Beta.DOM.HTML (div, a, span)
import Beta.DOM (text)

example =
  div { "data-testid": "example" }
    [ a { href: "https://example.com" }
        $ span { "aria-label": "somelabel" } "Example"
    , text " and so on..."
    ]

vs.

-- this is a bit unfair because the "simplified" DOM also exists and would make this quite a bit better
module Example where

import Prelude hiding (div)
import React.Basic.DOM (div, a, span)
import Foreign.Object (singleton) as Object

example =
  div
    { _data: Object.singleton "testid" "example"
    , children:
        [ a { href: "https://exmaple.com", children: [ span { _aria: Object.singleton "label" "somelabel", children: [ "Example" ] } ] }
        , text " and so on..."
        ]
    }

Trying it out / Installation

This is a work-in-progress library that works on its own and in conjunction with the existing react-basic-hooks-dom library.

I don't want to publish it yet, but you can easily integrate it via your packages.dhall file.

Add this to your packages.dhall file:

with react-basic-dom-beta =
      { dependencies =
          [ "datetime"
          , "effect"
          , "forgetmenot"
          , "functions"
          , "nullable"
          , "prelude"
          , "react-basic"
          , "react-basic-hooks"
          , "record"
          , "type-equality"
          , "typelevel-prelude"
          , "unsafe-coerce"
          , "web-dom"
          , "web-events"
          , "web-html"
          , "web-touchevents"
          ]
      , repo =
          "https://github.com/rowtype-yoga/purescript-react-basic-dom-beta.git"
      , version = "main"
      }

Then run:

spago install react-basic-dom-beta

Features and design goals

Documentation with examples for each component

Since there's no tooling in PureScript that will autocomplete possible record keys, I've decided to work around this limitation by providing some short documentation with the most important attributes for each component and a copy-pasteable exmaple.

There are also certain relationships between HTML elements that are very difficult to enforce in the type system, such as how to nest tags correctly (e.g. table, contains thead, and tbody which contains tr, which contains td or th, ...). I hope that the provided examples remedy these problems a lot since the documentation will popup when autocompleting the HTML tag's name.

Ability to pass any "aria-" or "data-" prop directly

This makes working with Hooks that return these props and expect the user to spread them onto your own component's props a lot easier and less error-prone.

aria-* props are typechecked

In contrast to data-* props, aria-* props are finite and can't have arbitrary names. This is an improvement that could be made in the current DOM as well, but I decided to skip it and do it here.

Improved readability by separating the children prop out

This is in line with HTML where the children are not part of the attributes and aren't named.

Allows passing single children and the empty array without runtime casts

React's createElement may be invoked without any children, or with zero to many children. The only way to approximate this in PureScript was via a typeclass as in the Simplified DOM.

The downside of this is that this stops working within Arrays because PureScript requires arrays to be of the same shape. There are two workarounds that I know of:

Manually casting the text to be JSX via text:

module Example where
import Beta.DOM (text)
import Beta.DOM.HTML.P (p)

x = [ text "A string", p {} "A p" ]

Or foregoing the array altogether and using an operator:

module Example where
import Beta.DOM.Internal ((++))
import Beta.DOM.HTML.P (p)

x = "A string" ++ p {} "A p"

I dislike both of these, because they are likely to trip beginners up.

Difference to the existing Simplified DOM

This DOM does not wrap anything in an Array because React's API does not require that anyway.

Another difference to the existing Simplified version is that this supports passing an empty array, while Simplified supports passing an array of anything that's has a ToJSX instance.

This is the difference in code with workarounds applied:

Simplified:
strings = p {} [ "A string", "Another string" ]
empties = p {} ([] :: _ JSX)
Beta:
strings = p {} "A stringAnother string"
empties = p {} []
Modules
Beta.DOM
Beta.DOM.Attributes
Beta.DOM.Attributes.AutoCapitalize
Beta.DOM.Attributes.Dir
Beta.DOM.Attributes.InputMode
Beta.DOM.Attributes.Target
Beta.DOM.Attributes.YesOrNo
Beta.DOM.Client
Beta.DOM.Event
Beta.DOM.HTML
Beta.DOM.HTML.A
Beta.DOM.HTML.Abbr
Beta.DOM.HTML.Address
Beta.DOM.HTML.Area
Beta.DOM.HTML.Article
Beta.DOM.HTML.Aside
Beta.DOM.HTML.Audio
Beta.DOM.HTML.B
Beta.DOM.HTML.Base
Beta.DOM.HTML.Bdi
Beta.DOM.HTML.Bdo
Beta.DOM.HTML.Blockquote
Beta.DOM.HTML.Body
Beta.DOM.HTML.Br
Beta.DOM.HTML.Button
Beta.DOM.HTML.Canvas
Beta.DOM.HTML.Caption
Beta.DOM.HTML.Cite
Beta.DOM.HTML.Code
Beta.DOM.HTML.Col
Beta.DOM.HTML.ColGroup
Beta.DOM.HTML.Data
Beta.DOM.HTML.DataList
Beta.DOM.HTML.Dd
Beta.DOM.HTML.Del
Beta.DOM.HTML.Details
Beta.DOM.HTML.Dfn
Beta.DOM.HTML.Dialog
Beta.DOM.HTML.Div
Beta.DOM.HTML.Dl
Beta.DOM.HTML.Dt
Beta.DOM.HTML.Em
Beta.DOM.HTML.Embed
Beta.DOM.HTML.FieldSet
Beta.DOM.HTML.Figcaption
Beta.DOM.HTML.Figure
Beta.DOM.HTML.Footer
Beta.DOM.HTML.Form
Beta.DOM.HTML.H
Beta.DOM.HTML.HTML
Beta.DOM.HTML.Head
Beta.DOM.HTML.Header
Beta.DOM.HTML.Hr
Beta.DOM.HTML.I
Beta.DOM.HTML.IFrame
Beta.DOM.HTML.Img
Beta.DOM.HTML.Input
Beta.DOM.HTML.Kbd
Beta.DOM.HTML.Label
Beta.DOM.HTML.Legend
Beta.DOM.HTML.Li
Beta.DOM.HTML.Link
Beta.DOM.HTML.Main
Beta.DOM.HTML.Map
Beta.DOM.HTML.Mark
Beta.DOM.HTML.Menu
Beta.DOM.HTML.Meta
Beta.DOM.HTML.Meter
Beta.DOM.HTML.Nav
Beta.DOM.HTML.NoScript
Beta.DOM.HTML.Object
Beta.DOM.HTML.Ol
Beta.DOM.HTML.Optgroup
Beta.DOM.HTML.Option
Beta.DOM.HTML.Output
Beta.DOM.HTML.P
Beta.DOM.HTML.Param
Beta.DOM.HTML.Picture
Beta.DOM.HTML.Pre
Beta.DOM.HTML.Progress
Beta.DOM.HTML.Q
Beta.DOM.HTML.Rp
Beta.DOM.HTML.Rt
Beta.DOM.HTML.Ruby
Beta.DOM.HTML.S
Beta.DOM.HTML.Samp
Beta.DOM.HTML.Script
Beta.DOM.HTML.Section
Beta.DOM.HTML.Select
Beta.DOM.HTML.Small
Beta.DOM.HTML.Source
Beta.DOM.HTML.Span
Beta.DOM.HTML.Strong
Beta.DOM.HTML.Style
Beta.DOM.HTML.Sub
Beta.DOM.HTML.Summary
Beta.DOM.HTML.Sup
Beta.DOM.HTML.Table
Beta.DOM.HTML.Tbody
Beta.DOM.HTML.Td
Beta.DOM.HTML.Template
Beta.DOM.HTML.Textarea
Beta.DOM.HTML.Tfoot
Beta.DOM.HTML.Th
Beta.DOM.HTML.Thead
Beta.DOM.HTML.Time
Beta.DOM.HTML.Title
Beta.DOM.HTML.Tr
Beta.DOM.HTML.Track
Beta.DOM.HTML.U
Beta.DOM.HTML.Ul
Beta.DOM.HTML.Var
Beta.DOM.HTML.Video
Beta.DOM.HTML.Wbr
Beta.DOM.Handler
Beta.DOM.Internal
Beta.DOM.Server
Dependencies