From 28caf1e143f2a40bba2f3da9626534f6d9ec7aa4 Mon Sep 17 00:00:00 2001 From: Mark Eibes Date: Fri, 25 Dec 2020 21:56:26 +0100 Subject: [PATCH] Add button --- .../Basic/Popper}/Placement/Types.purs | 2 +- src/Yoga/Block/Atom/Button/Story.purs | 37 ++++ src/Yoga/Block/Atom/Button/Style.purs | 11 + src/Yoga/Block/Atom/Button/Types.purs | 9 + src/Yoga/Block/Atom/Button/View.purs | 40 ++++ src/Yoga/Block/Atom/Input/Story.purs | 3 - src/Yoga/Block/Atom/Input/Style.purs | 8 +- src/Yoga/Block/Atom/Input/Types.purs | 7 +- src/Yoga/Block/Atom/Input/View.purs | 1 - src/Yoga/Block/Atom/Popover/Story.purs | 4 +- src/Yoga/Block/Atom/Popover/Style.purs | 8 +- src/Yoga/Block/Atom/Popover/View.purs | 4 +- src/Yoga/Block/Internal.purs | 202 ++++++++++++++++-- 13 files changed, 302 insertions(+), 34 deletions(-) rename src/{Yoga/Block/Atom/Input => React/Basic/Popper}/Placement/Types.purs (86%) create mode 100644 src/Yoga/Block/Atom/Button/Story.purs create mode 100644 src/Yoga/Block/Atom/Button/Style.purs create mode 100644 src/Yoga/Block/Atom/Button/Types.purs create mode 100644 src/Yoga/Block/Atom/Button/View.purs diff --git a/src/Yoga/Block/Atom/Input/Placement/Types.purs b/src/React/Basic/Popper/Placement/Types.purs similarity index 86% rename from src/Yoga/Block/Atom/Input/Placement/Types.purs rename to src/React/Basic/Popper/Placement/Types.purs index 29c7264..f6ae353 100644 --- a/src/Yoga/Block/Atom/Input/Placement/Types.purs +++ b/src/React/Basic/Popper/Placement/Types.purs @@ -1,4 +1,4 @@ -module Yoga.Block.Atom.Input.Placement.Types (render, Placement(..), Primary(..), Secondary(..)) where +module React.Basic.Popper.Placement.Types (render, Placement(..), Primary(..), Secondary(..)) where import Prelude import Data.Foldable (foldMap) diff --git a/src/Yoga/Block/Atom/Button/Story.purs b/src/Yoga/Block/Atom/Button/Story.purs new file mode 100644 index 0000000..0c001f8 --- /dev/null +++ b/src/Yoga/Block/Atom/Button/Story.purs @@ -0,0 +1,37 @@ +module Yoga.Block.Atom.Button.Story where + +import Prelude +import Effect (Effect) +import Effect.Unsafe (unsafePerformEffect) +import React.Basic (JSX, element, fragment) +import React.Basic.DOM as R +import React.Basic.Emotion as E +import React.Basic.Events (handler_) +import Yoga.Block.Atom.Button.View as Button +import Yoga.Block.Container.Style as Styles + +default ∷ + { decorators ∷ Array (Effect JSX -> JSX) + , title ∷ String + } +default = + { title: "Atom/Button" + , decorators: + [ \storyFn -> + R.div_ + [ element E.global { styles: Styles.global } + , unsafePerformEffect storyFn + ] + ] + } + +button ∷ Effect JSX +button = do + pure + $ fragment + [ R.div_ + [ R.h1_ [ R.text "Button Examples" ] + , R.h2_ [ R.text "Generic Button" ] + , element Button.component { value: "A Generic Button", onClick: handler_ mempty } + ] + ] diff --git a/src/Yoga/Block/Atom/Button/Style.purs b/src/Yoga/Block/Atom/Button/Style.purs new file mode 100644 index 0000000..6fc8307 --- /dev/null +++ b/src/Yoga/Block/Atom/Button/Style.purs @@ -0,0 +1,11 @@ +module Yoga.Block.Atom.Button.Style where + +import Yoga.Prelude.Style + +type Props f r + = ( css ∷ f Style + | r + ) + +button :: Style +button = css {} diff --git a/src/Yoga/Block/Atom/Button/Types.purs b/src/Yoga/Block/Atom/Button/Types.purs new file mode 100644 index 0000000..b2dd056 --- /dev/null +++ b/src/Yoga/Block/Atom/Button/Types.purs @@ -0,0 +1,9 @@ +module Yoga.Block.Atom.Button.Types where + +import Prelude + +data ButtonType + = Primary + | Secondary + | Generic +derive instance eqHTMLButton ∷ Eq ButtonType diff --git a/src/Yoga/Block/Atom/Button/View.purs b/src/Yoga/Block/Atom/Button/View.purs new file mode 100644 index 0000000..05febe4 --- /dev/null +++ b/src/Yoga/Block/Atom/Button/View.purs @@ -0,0 +1,40 @@ +module Yoga.Block.Atom.Button.View where + +import Yoga.Prelude.View +import Data.Symbol (SProxy(..)) +import Record.Builder as RB +import Yoga.Block.Atom.Button.Style as Style +import Yoga.Block.Atom.Button.Types (ButtonType) +import Yoga.Block.Internal (ButtonProps, emotionButton) + +type PropsF f + = ( buttonType ∷ f ButtonType + | Style.Props f ButtonProps + ) + +type Props + = PropsF Id + +type PropsOptional + = PropsF OptionalProp + +key :: forall t1. SProxy t1 +key = SProxy + +component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p } +component = rawComponent + +rawComponent ∷ ∀ p. ReactComponent { | p } +rawComponent = + mkForwardRefComponent "Button" do + \(props ∷ { | PropsOptional }) propsRef -> React.do + pure + $ emotionButton propsRef + ( props + # RB.build + ( RB.delete (key :: _ "css") >>> RB.delete (key :: _ "buttonType") + ) + ) + { className: "ry-button" + , css: Style.button + } diff --git a/src/Yoga/Block/Atom/Input/Story.purs b/src/Yoga/Block/Atom/Input/Story.purs index 19743aa..7cbf1c0 100644 --- a/src/Yoga/Block/Atom/Input/Story.purs +++ b/src/Yoga/Block/Atom/Input/Story.purs @@ -73,9 +73,6 @@ input = do , element Input.component { type: HTMLInput.Text, value: "", label: NonEmptyString "Heinzi", onChange: handler_ mempty } , R.h2_ [ R.text "Search Input" ] , element Input.component { type: HTMLInput.Search, placeholder: "Search...", onChange: handler_ mempty } - , R.h2_ [ R.text "Button" ] - , element Input.component { type: HTMLInput.Button, value: "A button", onChange: handler_ mempty } - , R.h2_ [ R.text "Submit" ] -- , element Input.component { type: "submit" } -- , R.h2_ [ R.text "Radio" ] -- , element Input.component { type: "radio" } diff --git a/src/Yoga/Block/Atom/Input/Style.purs b/src/Yoga/Block/Atom/Input/Style.purs index ca726a2..257650c 100644 --- a/src/Yoga/Block/Atom/Input/Style.purs +++ b/src/Yoga/Block/Atom/Input/Style.purs @@ -4,10 +4,10 @@ import Yoga.Prelude.Style import Data.Interpolate (i) import Yoga.Block.Container.Style (colour) -type Props f r = - ( css ∷ f Style - | r - ) +type Props f r + = ( css ∷ f Style + | r + ) leftIconSize ∷ StyleProperty leftIconSize = var "--left-icon-size" diff --git a/src/Yoga/Block/Atom/Input/Types.purs b/src/Yoga/Block/Atom/Input/Types.purs index ec46257..35e0111 100644 --- a/src/Yoga/Block/Atom/Input/Types.purs +++ b/src/Yoga/Block/Atom/Input/Types.purs @@ -2,9 +2,10 @@ module Yoga.Block.Atom.Input.Types where import Prelude +-- No support for "button" because of the dedicated +-- HTML Element data HTMLInput - = Button - | Checkbox + = Checkbox | Color | Date | DatetimeLocal @@ -25,12 +26,10 @@ data HTMLInput | Time | Url | Week - derive instance eqHTMLInput ∷ Eq HTMLInput toString ∷ HTMLInput -> String toString = case _ of - Button -> "button" Checkbox -> "checkbox" Color -> "color" Date -> "date" diff --git a/src/Yoga/Block/Atom/Input/View.purs b/src/Yoga/Block/Atom/Input/View.purs index 7c7aa6e..902a8e8 100644 --- a/src/Yoga/Block/Atom/Input/View.purs +++ b/src/Yoga/Block/Atom/Input/View.purs @@ -4,7 +4,6 @@ import Yoga.Prelude.View import Data.String.NonEmpty (NonEmptyString) import Data.String.NonEmpty as NonEmptyString import Data.Symbol (SProxy(..)) -import Effect.Uncurried (mkEffectFn1, runEffectFn1) import Foreign.Object (Object) import Foreign.Object as Object import Framer.Motion as M diff --git a/src/Yoga/Block/Atom/Popover/Story.purs b/src/Yoga/Block/Atom/Popover/Story.purs index 146e2df..bc3af52 100644 --- a/src/Yoga/Block/Atom/Popover/Story.purs +++ b/src/Yoga/Block/Atom/Popover/Story.purs @@ -22,12 +22,12 @@ import React.Basic.Emotion as E import React.Basic.Events (handler, handler_) import React.Basic.Hooks (reactComponent) import React.Basic.Hooks as React +import React.Basic.Popper.Placement.Types (Placement(..)) +import React.Basic.Popper.Placement.Types as Placement import React.Basic.Popper.Types (nullRef) import Unsafe.Coerce (unsafeCoerce) import Yoga ((/>), ()) import Yoga.Block.Atom.Input as Input -import Yoga.Block.Atom.Input.Placement.Types (Placement(..)) -import Yoga.Block.Atom.Input.Placement.Types as Placement import Yoga.Block.Atom.Input.Types as HTMLInput import Yoga.Block.Atom.Popover as Popover import Yoga.Block.Container.Style as Styles diff --git a/src/Yoga/Block/Atom/Popover/Style.purs b/src/Yoga/Block/Atom/Popover/Style.purs index 09a7121..4dc0203 100644 --- a/src/Yoga/Block/Atom/Popover/Style.purs +++ b/src/Yoga/Block/Atom/Popover/Style.purs @@ -2,10 +2,10 @@ module Yoga.Block.Atom.Popover.Style where import Yoga.Prelude.Style -type Props f r = - ( css ∷ f Style - | r - ) +type Props f r + = ( css ∷ f Style + | r + ) content ∷ Style content = diff --git a/src/Yoga/Block/Atom/Popover/View.purs b/src/Yoga/Block/Atom/Popover/View.purs index 6e3c08c..81a10f4 100644 --- a/src/Yoga/Block/Atom/Popover/View.purs +++ b/src/Yoga/Block/Atom/Popover/View.purs @@ -4,10 +4,10 @@ import Yoga.Prelude.View import Effect.Uncurried (mkEffectFn1) import React.Basic.Hooks as React import React.Basic.Popper.Hook (usePopper) +import React.Basic.Popper.Placement.Types (Placement) +import React.Basic.Popper.Placement.Types as Placement import React.Basic.Popper.Types (modifierOffset, nullRef) import Unsafe.Coerce (unsafeCoerce) -import Yoga.Block.Atom.Input.Placement.Types (Placement) -import Yoga.Block.Atom.Input.Placement.Types as Placement import Yoga.Block.Atom.Popover.Style as Style type PropsF f diff --git a/src/Yoga/Block/Internal.purs b/src/Yoga/Block/Internal.purs index 9b7080b..37b79ab 100644 --- a/src/Yoga/Block/Internal.purs +++ b/src/Yoga/Block/Internal.purs @@ -9,9 +9,12 @@ module Yoga.Block.Internal , DivPropsF , InputProps , InputPropsF + , ButtonProps + , ButtonPropsF , NodeRef , emotionDiv , emotionInput + , emotionButton , module Yoga.Block.Internal.OptionalProp , module Yoga.Block.Internal.CSS , unsafeUnionDroppingUndefined @@ -35,13 +38,14 @@ import Foreign.Object (Object) import Prim.Row (class Lacks, class Union) import Prim.Row as Row import Prim.RowList as RL -import React.Basic.DOM (CSS, unsafeCreateDOMComponent) +import React.Basic.DOM (CSS, Props_input, Props_button, unsafeCreateDOMComponent) import React.Basic.Emotion (Style) import React.Basic.Emotion as E import React.Basic.Events (EventHandler) import React.Basic.Hooks (JSX, ReactComponent, Ref, Render, readRefMaybe) import Record.Extra (class Keys, keys) import Type.Data.Row (RProxy(..)) +import Type.Row (type (+)) import Unsafe.Coerce (unsafeCoerce) import Untagged.Union (UndefinedOr, uorToMaybe) import Web.DOM (Node) @@ -136,18 +140,7 @@ pickDefined ref = runFn3 pickDefinedFn ref ks where ks = Array.fromFoldable $ keys (RProxy ∷ RProxy b) -emotionInput_ ∷ - ∀ props props_. - Lacks "ref" props => - Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | InputProps ) => - { | InputProps } -> - { className ∷ String - , css ∷ Style - | props - } -> - JSX -emotionInput_ = unsafeEmotion unsafeInput - +-- [TODO] Delete? emotionInputKeyed_ ∷ ∀ props props_. Lacks "ref" props => @@ -161,6 +154,18 @@ emotionInputKeyed_ ∷ JSX emotionInputKeyed_ = unsafeEmotionKeyed unsafeInput +emotionInput_ ∷ + ∀ props props_. + Lacks "ref" props => + Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | InputProps ) => + { | InputProps } -> + { className ∷ String + , css ∷ Style + | props + } -> + JSX +emotionInput_ = unsafeEmotion unsafeInput + emotionInput ∷ ∀ props props_ more. Lacks "ref" props => @@ -177,6 +182,34 @@ emotionInput ref = emotionInput_ <<< pickDefined ref unsafeInput ∷ ∀ r. ReactComponent (Record r) unsafeInput = dangerous "input" +emotionButton_ ∷ + ∀ props props_. + Lacks "ref" props => + Union props props_ ( className ∷ String, css ∷ Style | ButtonProps ) => + { | ButtonProps } -> + { className ∷ String + , css ∷ Style + | props + } -> + JSX +emotionButton_ = unsafeEmotion unsafeButton + +emotionButton ∷ + ∀ props props_ more. + Lacks "ref" props => + Union props props_ ( className ∷ String, css ∷ Style | ButtonProps ) => + Ref (Nullable Node) -> + { | ButtonPropsF Id more } -> + { className ∷ String + , css ∷ Style + | props + } -> + JSX +emotionButton ref = emotionButton_ <<< pickDefined ref + +unsafeButton ∷ ∀ r. ReactComponent (Record r) +unsafeButton = dangerous "button" + dangerous ∷ ∀ props. String -> ReactComponent (Record props) dangerous = unsafePerformEffect <<< unsafeCreateDOMComponent @@ -479,3 +512,146 @@ type InputPropsF f more , max ∷ f (String) | more ) + +type ButtonProps + = ButtonPropsF Id () + +type ButtonPropsF f more + = ( _aria :: f (Object String) + , _data :: f (Object String) + , about :: f String + , acceptCharset :: f String + , accessKey :: f String + , allowFullScreen :: f Boolean + , allowTransparency :: f Boolean + , autoFocus :: f Boolean + , autoPlay :: f Boolean + , capture :: f Boolean + , cellPadding :: f String + , cellSpacing :: f String + , charSet :: f String + , children :: f (Array JSX) + , classID :: f String + , className :: f String + , colSpan :: f Int + , contentEditable :: f Boolean + , contextMenu :: f String + , crossOrigin :: f String + , dangerouslySetInnerHTML :: f { __html :: String } + , datatype :: f String + , dateTime :: f String + , dir :: f String + , disabled :: f Boolean + , draggable :: f Boolean + , encType :: f String + , form :: f String + , formAction :: f String + , formEncType :: f String + , formMethod :: f String + , formNoValidate :: f Boolean + , formTarget :: f String + , frameBorder :: f String + , hidden :: f Boolean + , hrefLang :: f String + , htmlFor :: f String + , httpEquiv :: f String + , icon :: f String + , id :: f String + , inlist :: f String + , inputMode :: f String + , is :: f String + , itemID :: f String + , itemProp :: f String + , itemRef :: f String + , itemScope :: f Boolean + , itemType :: f String + , key :: f String + , keyParams :: f String + , keyType :: f String + , lang :: f String + , marginHeight :: f String + , marginWidth :: f String + , maxLength :: f Int + , mediaGroup :: f String + , minLength :: f Int + , name :: f String + , noValidate :: f Boolean + , onAnimationEnd :: f EventHandler + , onAnimationIteration :: f EventHandler + , onAnimationStart :: f EventHandler + , onBlur :: f EventHandler + , onClick :: f EventHandler + , onCompositionEnd :: f EventHandler + , onCompositionStart :: f EventHandler + , onCompositionUpdate :: f EventHandler + , onContextMenu :: f EventHandler + , onCopy :: f EventHandler + , onCut :: f EventHandler + , onDoubleClick :: f EventHandler + , onDrag :: f EventHandler + , onDragEnd :: f EventHandler + , onDragEnter :: f EventHandler + , onDragExit :: f EventHandler + , onDragLeave :: f EventHandler + , onDragOver :: f EventHandler + , onDragStart :: f EventHandler + , onDrop :: f EventHandler + , onFocus :: f EventHandler + , onGotPointerCapture :: f EventHandler + , onInvalid :: f EventHandler + , onKeyDown :: f EventHandler + , onKeyPress :: f EventHandler + , onKeyUp :: f EventHandler + , onLostPointerCapture :: f EventHandler + , onMouseDown :: f EventHandler + , onMouseEnter :: f EventHandler + , onMouseLeave :: f EventHandler + , onMouseMove :: f EventHandler + , onMouseOut :: f EventHandler + , onMouseOver :: f EventHandler + , onMouseUp :: f EventHandler + , onPaste :: f EventHandler + , onPointerCancel :: f EventHandler + , onPointerDown :: f EventHandler + , onPointerEnter :: f EventHandler + , onPointerLeave :: f EventHandler + , onPointerMove :: f EventHandler + , onPointerOut :: f EventHandler + , onPointerOver :: f EventHandler + , onPointerUp :: f EventHandler + , onSelect :: f EventHandler + , onSubmit :: f EventHandler + , onTouchCancel :: f EventHandler + , onTouchEnd :: f EventHandler + , onTouchMove :: f EventHandler + , onTouchStart :: f EventHandler + , onTransitionEnd :: f EventHandler + , onWheel :: f EventHandler + , prefix :: f String + , property :: f String + , radioGroup :: f String + , readOnly :: f Boolean + , ref :: f (Ref (Nullable Node)) + , resource :: f String + , role :: f String + , rowSpan :: f Int + , scoped :: f Boolean + , seamless :: f Boolean + , security :: f String + , spellCheck :: f Boolean + , srcDoc :: f JSX + , srcLang :: f String + , srcSet :: f String + , style :: f CSS + , suppressContentEditableWarning :: f Boolean + , tabIndex :: f Int + , title :: f String + , type :: f String + , typeof :: f String + , unselectable :: f Boolean + , useMap :: f String + , value :: f String + , vocab :: f String + , wmode :: f String + | more + )