mirror of
https://github.com/rowtype-yoga/ry-blocks.git
synced 2024-09-17 16:27:33 +03:00
Input work
This commit is contained in:
parent
774db186ef
commit
c32928933f
1
.psci_modules/index.js
Normal file
1
.psci_modules/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
require('$PSCI')['$main']();
|
8
convert-more.fish
Normal file
8
convert-more.fish
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
for f in (ls src/Yoga/Block/Icon/SVG/*.svg)
|
||||||
|
npx svgo -i $f
|
||||||
|
end
|
||||||
|
node convert-svgs.js
|
||||||
|
for f in (ls src/Yoga/Block/Icon/SVG/*.purs)
|
||||||
|
sed -i "" 's/stroke: "#333"/stroke: "var(--stroke-colour)"/g' $f
|
||||||
|
end
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const svg2psreact = require("svg2psreact");
|
const svg2psreact = require("svg2psreact");
|
||||||
|
|
||||||
const assetsDir = path.join(__dirname, 'src', 'Assets');
|
const assetsDir = path.join(__dirname, 'src', 'Yoga', 'Block', 'Icon', 'SVG');
|
||||||
|
|
||||||
svg2psreact.convertAllSVGsInDirectory("Assets", assetsDir)
|
svg2psreact.convertAllSVGsInDirectory("Yoga.Block.Icon.SVG", assetsDir)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"compression-webpack-plugin": "^6.0.3",
|
"compression-webpack-plugin": "^6.0.3",
|
||||||
"framer-motion": "^2.7.0",
|
"framer-motion": "^3.0.0",
|
||||||
"html-webpack-plugin": "^4.5.0",
|
"html-webpack-plugin": "^4.5.0",
|
||||||
"jsdom": "^16.3.0",
|
"jsdom": "^16.3.0",
|
||||||
"jsdom-global": "^3.0.2",
|
"jsdom-global": "^3.0.2",
|
||||||
|
@ -119,7 +119,7 @@ let additions =
|
|||||||
|
|
||||||
|
|
||||||
let upstream =
|
let upstream =
|
||||||
https://github.com/purescript/package-sets/releases/download/psc-0.13.8-20201021/packages.dhall sha256:55ebdbda1bd6ede4d5307fbc1ef19988c80271b4225d833c8d6fb9b6fb1aa6d8
|
https://github.com/purescript/package-sets/releases/download/psc-0.13.8-20201217/packages.dhall sha256:f46d45e29977f3b57717b56d20a5ceac12532224516eea3012a4688f22ac1539
|
||||||
|
|
||||||
let overrides =
|
let overrides =
|
||||||
{ spec-discovery = upstream.spec-discovery // { version = "master" }
|
{ spec-discovery = upstream.spec-discovery // { version = "master" }
|
||||||
|
@ -18,6 +18,7 @@ You can edit this file as you like.
|
|||||||
, "routing-duplex"
|
, "routing-duplex"
|
||||||
, "spec-discovery"
|
, "spec-discovery"
|
||||||
, "untagged-union"
|
, "untagged-union"
|
||||||
|
, "web-uievents"
|
||||||
]
|
]
|
||||||
, packages = ./packages.dhall
|
, packages = ./packages.dhall
|
||||||
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
|
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
|
||||||
|
@ -6,6 +6,14 @@ module Framer.Motion
|
|||||||
, callback
|
, callback
|
||||||
, class EffectFnMaker
|
, class EffectFnMaker
|
||||||
, toEffectFn
|
, toEffectFn
|
||||||
|
, OnHoverStart
|
||||||
|
, onHoverStart
|
||||||
|
, customProp
|
||||||
|
, OnHoverEnd
|
||||||
|
, onHoverEnd
|
||||||
|
, whileHover
|
||||||
|
, WhileHover
|
||||||
|
, EventInfo
|
||||||
, OnTap
|
, OnTap
|
||||||
, TapInfo
|
, TapInfo
|
||||||
, OnTapStart
|
, OnTapStart
|
||||||
@ -80,6 +88,7 @@ import Data.Nullable (Nullable)
|
|||||||
import Data.Symbol (class IsSymbol, SProxy, reflectSymbol)
|
import Data.Symbol (class IsSymbol, SProxy, reflectSymbol)
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
import Effect.Uncurried (EffectFn1, EffectFn2, mkEffectFn1, mkEffectFn2)
|
import Effect.Uncurried (EffectFn1, EffectFn2, mkEffectFn1, mkEffectFn2)
|
||||||
|
import Foreign (Foreign, unsafeToForeign)
|
||||||
import Foreign.Object (Object)
|
import Foreign.Object (Object)
|
||||||
import Heterogeneous.Mapping (class HMapWithIndex, class MappingWithIndex, hmapWithIndex)
|
import Heterogeneous.Mapping (class HMapWithIndex, class MappingWithIndex, hmapWithIndex)
|
||||||
import Literals.Undefined (Undefined)
|
import Literals.Undefined (Undefined)
|
||||||
@ -97,6 +106,7 @@ import Untagged.Castable (class Castable, cast)
|
|||||||
import Untagged.Union (type (|+|))
|
import Untagged.Union (type (|+|))
|
||||||
import Web.DOM (Node)
|
import Web.DOM (Node)
|
||||||
import Web.Event.Internal.Types (Event)
|
import Web.Event.Internal.Types (Event)
|
||||||
|
import Web.UIEvent.MouseEvent (MouseEvent)
|
||||||
import Yoga.Block.Internal (Id)
|
import Yoga.Block.Internal (Id)
|
||||||
|
|
||||||
foreign import divImpl ∷ ∀ a. ReactComponent { | a }
|
foreign import divImpl ∷ ∀ a. ReactComponent { | a }
|
||||||
@ -216,6 +226,28 @@ onTap fn2 = cast (mkEffectFn2 fn2)
|
|||||||
onTapCancel ∷ (Event -> TapInfo -> Effect Unit) -> OnTap
|
onTapCancel ∷ (Event -> TapInfo -> Effect Unit) -> OnTap
|
||||||
onTapCancel fn2 = cast (mkEffectFn2 fn2)
|
onTapCancel fn2 = cast (mkEffectFn2 fn2)
|
||||||
|
|
||||||
|
type EventInfo =
|
||||||
|
{ point ∷ { x ∷ Number, y ∷ Number }
|
||||||
|
}
|
||||||
|
|
||||||
|
type WhileHover =
|
||||||
|
(EffectFn2 MouseEvent EventInfo Unit |+| Undefined)
|
||||||
|
|
||||||
|
type OnHoverEnd =
|
||||||
|
(EffectFn2 MouseEvent EventInfo Unit |+| Undefined)
|
||||||
|
|
||||||
|
type OnHoverStart =
|
||||||
|
(EffectFn2 MouseEvent EventInfo Unit |+| Undefined)
|
||||||
|
|
||||||
|
onHoverStart ∷ (MouseEvent -> EventInfo -> Effect Unit) -> OnHoverStart
|
||||||
|
onHoverStart = cast <<< toEffectFn
|
||||||
|
|
||||||
|
onHoverEnd ∷ (MouseEvent -> EventInfo -> Effect Unit) -> OnHoverEnd
|
||||||
|
onHoverEnd = cast <<< toEffectFn
|
||||||
|
|
||||||
|
whileHover ∷ ∀ c. Castable c WhileHover => c -> WhileHover
|
||||||
|
whileHover = cast
|
||||||
|
|
||||||
type TapInfo =
|
type TapInfo =
|
||||||
{ x ∷ Number, y ∷ Number }
|
{ x ∷ Number, y ∷ Number }
|
||||||
|
|
||||||
@ -250,9 +282,13 @@ onDragEnd = cast <<< toEffectFn
|
|||||||
onDrag ∷ (Event -> PanInfo -> Effect Unit) -> OnDrag
|
onDrag ∷ (Event -> PanInfo -> Effect Unit) -> OnDrag
|
||||||
onDrag fn2 = cast (mkEffectFn2 fn2)
|
onDrag fn2 = cast (mkEffectFn2 fn2)
|
||||||
|
|
||||||
|
customProp ∷ ∀ a. a -> Foreign
|
||||||
|
customProp = unsafeToForeign
|
||||||
|
|
||||||
type MotionPropsF f r =
|
type MotionPropsF f r =
|
||||||
( initial ∷ f Initial
|
( initial ∷ f Initial
|
||||||
, animate ∷ f Animate
|
, animate ∷ f Animate
|
||||||
|
, custom ∷ f Foreign
|
||||||
, drag ∷ f Drag
|
, drag ∷ f Drag
|
||||||
, dragMomentum ∷ f DragMomentum
|
, dragMomentum ∷ f DragMomentum
|
||||||
, dragElastic ∷ f DragElastic
|
, dragElastic ∷ f DragElastic
|
||||||
@ -270,6 +306,9 @@ type MotionPropsF f r =
|
|||||||
, onTapStart ∷ f OnTapStart
|
, onTapStart ∷ f OnTapStart
|
||||||
, onTapEnd ∷ f OnTapEnd
|
, onTapEnd ∷ f OnTapEnd
|
||||||
, onTapCancel ∷ f OnTapCancel
|
, onTapCancel ∷ f OnTapCancel
|
||||||
|
, whileHover ∷ f WhileHover
|
||||||
|
, onHoverStart ∷ f OnHoverStart
|
||||||
|
, onHoverEnd ∷ f OnHoverEnd
|
||||||
, exit ∷ f Exit
|
, exit ∷ f Exit
|
||||||
| r
|
| r
|
||||||
)
|
)
|
||||||
|
@ -7,43 +7,11 @@ import Effect.Uncurried (EffectFn3, runEffectFn3)
|
|||||||
import Foreign.Object (Object)
|
import Foreign.Object (Object)
|
||||||
import Foreign.Object as Object
|
import Foreign.Object as Object
|
||||||
import Prim.Row (class Union)
|
import Prim.Row (class Union)
|
||||||
import React.Basic.DOM (CSS)
|
import Yoga.Prelude.View (Hook, unsafeHook)
|
||||||
import Unsafe.Coerce (unsafeCoerce)
|
import React.Basic.Popper.Types (Options, PopperData, PopperElement, ReferenceElement)
|
||||||
import Yoga.Prelude.View (Hook, NodeRef, unsafeHook)
|
|
||||||
|
|
||||||
foreign import data UsePopper ∷ Type -> Type -> Type
|
foreign import data UsePopper ∷ Type -> Type -> Type
|
||||||
|
|
||||||
type ReferenceElement =
|
|
||||||
NodeRef
|
|
||||||
|
|
||||||
type PopperElement =
|
|
||||||
NodeRef
|
|
||||||
|
|
||||||
type ArrowElement =
|
|
||||||
NodeRef
|
|
||||||
|
|
||||||
type DataAttributes =
|
|
||||||
{ popper ∷ Object String, arrow ∷ Object String }
|
|
||||||
|
|
||||||
type Styles =
|
|
||||||
{ popper ∷ CSS, arrow ∷ CSS }
|
|
||||||
|
|
||||||
type PopperData =
|
|
||||||
{ styles ∷ Styles, attributes ∷ DataAttributes }
|
|
||||||
|
|
||||||
foreign import data Modifier ∷ Type
|
|
||||||
|
|
||||||
modifierArrow ∷ ArrowElement -> Modifier
|
|
||||||
modifierArrow element = unsafeCoerce { name: "arrow", options: { element } }
|
|
||||||
|
|
||||||
modifierOffset ∷ { x ∷ Number, y ∷ Number } -> Modifier
|
|
||||||
modifierOffset { x, y } = unsafeCoerce { name: "offset", options: { offset: [ x, y ] } }
|
|
||||||
|
|
||||||
type Options =
|
|
||||||
( modifiers ∷ Array Modifier
|
|
||||||
, strategy ∷ String
|
|
||||||
)
|
|
||||||
|
|
||||||
foreign import usePopperImpl ∷ ∀ opts. EffectFn3 ReferenceElement PopperElement { | opts } PopperData
|
foreign import usePopperImpl ∷ ∀ opts. EffectFn3 ReferenceElement PopperElement { | opts } PopperData
|
||||||
|
|
||||||
toDataAttributes ∷ Object String -> Object String
|
toDataAttributes ∷ Object String -> Object String
|
||||||
|
@ -1,27 +1,24 @@
|
|||||||
module React.Basic.Popper.Story where
|
module React.Basic.Popper.Story where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
import Color as Color
|
import Data.Interpolate (i)
|
||||||
import Data.Maybe (Maybe(..))
|
|
||||||
import Data.Nullable (null)
|
import Data.Nullable (null)
|
||||||
import Data.Tuple.Nested ((/\))
|
import Data.Tuple.Nested ((/\))
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
import Effect.Uncurried (mkEffectFn1)
|
import Effect.Uncurried (mkEffectFn1)
|
||||||
import Effect.Unsafe (unsafePerformEffect)
|
import Effect.Unsafe (unsafePerformEffect)
|
||||||
import Framer.Motion (onTap)
|
|
||||||
import Framer.Motion as Motion
|
import Framer.Motion as Motion
|
||||||
import React.Basic (JSX, element, fragment)
|
import React.Basic (JSX, element, fragment)
|
||||||
import React.Basic.DOM as R
|
import React.Basic.DOM as R
|
||||||
import React.Basic.Emotion as E
|
import React.Basic.Emotion as E
|
||||||
import React.Basic.Hooks as React
|
import React.Basic.Hooks as React
|
||||||
import React.Basic.Popper.Hook (modifierArrow, modifierOffset, usePopper)
|
import React.Basic.Popper.Hook (usePopper)
|
||||||
|
import React.Basic.Popper.Types (modifierArrow, modifierOffset)
|
||||||
import Unsafe.Coerce (unsafeCoerce)
|
import Unsafe.Coerce (unsafeCoerce)
|
||||||
import Yoga.Block as Block
|
import Yoga.Block as Block
|
||||||
import Yoga.Block.Atom.Toggle as Toggle
|
|
||||||
import Yoga.Block.Container.Style (DarkOrLightMode(..))
|
|
||||||
import Yoga.Block.Container.Style as Styles
|
import Yoga.Block.Container.Style as Styles
|
||||||
import Yoga.Block.Internal.CSS (nest)
|
import Yoga.Block.Internal.CSS (nest)
|
||||||
import Yoga.Prelude.View (NodeRef, el, styled, styledLeaf)
|
import Yoga.Prelude.View (NodeRef, el, guard, handler, preventDefault, styled, styledLeaf)
|
||||||
|
|
||||||
default ∷
|
default ∷
|
||||||
{ decorators ∷ Array (Effect JSX -> JSX)
|
{ decorators ∷ Array (Effect JSX -> JSX)
|
||||||
@ -136,6 +133,7 @@ animatedPopper = do
|
|||||||
|
|
||||||
mkBasicExample =
|
mkBasicExample =
|
||||||
React.reactComponent "Popper example" \p -> React.do
|
React.reactComponent "Popper example" \p -> React.do
|
||||||
|
-- Hooks
|
||||||
referenceElement /\ setReferenceElement <- React.useState' nullRef
|
referenceElement /\ setReferenceElement <- React.useState' nullRef
|
||||||
popperElement /\ setPopperElement <- React.useState' nullRef
|
popperElement /\ setPopperElement <- React.useState' nullRef
|
||||||
arrowElement /\ setArrowElement <- React.useState' nullRef
|
arrowElement /\ setArrowElement <- React.useState' nullRef
|
||||||
@ -143,63 +141,105 @@ animatedPopper = do
|
|||||||
usePopper referenceElement popperElement
|
usePopper referenceElement popperElement
|
||||||
{ modifiers:
|
{ modifiers:
|
||||||
[ modifierArrow arrowElement
|
[ modifierArrow arrowElement
|
||||||
, modifierOffset { x: 0.0, y: 8.0 }
|
, modifierOffset { x: 0.0, y: 12.0 }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
pure
|
on /\ setOn <- React.useState' true
|
||||||
$ fragment
|
-- Handlers
|
||||||
$ [ element R.div'
|
let buttonClicked = setOn (not on)
|
||||||
{ ref: unsafeCoerce (mkEffectFn1 setReferenceElement)
|
-- Elements
|
||||||
, children: [ R.text "Reference element" ]
|
let
|
||||||
|
result =
|
||||||
|
fragment
|
||||||
|
$ [ refElem
|
||||||
|
, popperEl
|
||||||
|
[ animatePresence
|
||||||
|
$ guard on
|
||||||
|
[ content
|
||||||
|
[ el Block.box {} [ R.text "Ich bin Stinky Bill" ]
|
||||||
|
, arrow
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
animatePresence =
|
||||||
|
el Motion.animatePresence
|
||||||
|
{ initial: false
|
||||||
}
|
}
|
||||||
, el Motion.animatePresence {}
|
content =
|
||||||
[ styled Motion.div
|
styled Motion.div
|
||||||
|
{ className: "popper-element-content"
|
||||||
|
, css: contentCss
|
||||||
|
, initial: Motion.initial $ R.css { opacity: [ 1.0, 0.8, 0.0 ], scale: [ 1.0, 0.85 ] }
|
||||||
|
, animate: Motion.animate $ R.css { opacity: [ 0.0, 0.3, 1.0 ], scale: [ 0.0, 1.05, 1.0, 0.98, 1.01, 1.0 ] }
|
||||||
|
, exit: Motion.exit $ R.css { opacity: [ 1.0, 0.8, 0.0 ], scale: [ 1.0, 0.85 ] }
|
||||||
|
, transition: Motion.transition { duration: 0.2 }
|
||||||
|
, key: "container"
|
||||||
|
}
|
||||||
|
popperEl =
|
||||||
|
styled R.div'
|
||||||
{ className: "popper-element"
|
{ className: "popper-element"
|
||||||
, key: "heinz"
|
, css: popperCss
|
||||||
, css:
|
|
||||||
E.css
|
|
||||||
{ background: E.str "darkslateblue"
|
|
||||||
, borderRadius: E.str "8px"
|
|
||||||
, display: E.str "block"
|
|
||||||
, padding: E.str "4px 8px"
|
|
||||||
, "&[data-popper-placement^='top'] > .popper-arrow":
|
|
||||||
nest { bottom: E.str "-4px" }
|
|
||||||
, "&[data-popper-placement^='bottom'] > .popper-arrow":
|
|
||||||
nest { top: E.str "-4px" }
|
|
||||||
, "&[data-popper-placement^='left'] > .popper-arrow":
|
|
||||||
nest { right: E.str "-4px" }
|
|
||||||
, "&[data-popper-placement^='right'] > .popper-arrow":
|
|
||||||
nest { left: E.str "-4px" }
|
|
||||||
}
|
|
||||||
, ref: unsafeCoerce (mkEffectFn1 setPopperElement)
|
, ref: unsafeCoerce (mkEffectFn1 setPopperElement)
|
||||||
, style: styles.popper
|
, style: styles.popper
|
||||||
, _data: attributes.popper
|
, _data: attributes.popper
|
||||||
}
|
}
|
||||||
[ R.text "Popper Element"
|
arrow =
|
||||||
, styledLeaf R.div'
|
styledLeaf R.div'
|
||||||
{ className: "popper-arrow"
|
{ className: "popper-arrow"
|
||||||
, id: "arrow"
|
, id: "arrow"
|
||||||
, css:
|
, css: arrowCss
|
||||||
|
, ref: unsafeCoerce (mkEffectFn1 setArrowElement)
|
||||||
|
, style: styles.arrow
|
||||||
|
, _data: attributes.arrow
|
||||||
|
}
|
||||||
|
refElem =
|
||||||
|
element R.button'
|
||||||
|
{ ref: unsafeCoerce (mkEffectFn1 setReferenceElement)
|
||||||
|
, children: [ R.text "Reference element" ]
|
||||||
|
, onClick: handler preventDefault (const buttonClicked)
|
||||||
|
}
|
||||||
|
pure result
|
||||||
|
|
||||||
|
backgroundColour = "var(--highlight)"
|
||||||
|
|
||||||
|
backgroundColour2 = "rgb(100, 160, 240)"
|
||||||
|
|
||||||
|
arrowCss =
|
||||||
E.css
|
E.css
|
||||||
{ position: E.str "absolute"
|
{ position: E.str "absolute"
|
||||||
, width: E.str "8px"
|
, width: E.str "8px"
|
||||||
, height: E.str "8px"
|
, height: E.str "8px"
|
||||||
, zIndex: E.str "-1"
|
, zIndex: E.str "0"
|
||||||
, "&::before":
|
, "&::before":
|
||||||
nest
|
nest
|
||||||
{ position: E.str "absolute"
|
{ position: E.str "absolute"
|
||||||
, width: E.str "8px"
|
, width: E.str "8px"
|
||||||
, height: E.str "8px"
|
, height: E.str "8px"
|
||||||
, zIndex: E.str "-1"
|
|
||||||
, content: E.str "''"
|
, content: E.str "''"
|
||||||
, transform: E.str "rotate(45deg)"
|
, transform: E.str "rotate(45deg)"
|
||||||
, background: E.str "darkslateblue"
|
, background: E.str backgroundColour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
, ref: unsafeCoerce (mkEffectFn1 setArrowElement)
|
|
||||||
, style: styles.arrow
|
contentCss =
|
||||||
, _data: attributes.arrow
|
E.css
|
||||||
|
{ background: E.str $ i "linear-gradient(0deg," backgroundColour "," backgroundColour2 "," backgroundColour ")"
|
||||||
|
, fontSize: E.str "14px"
|
||||||
|
, zIndex: E.str "-1"
|
||||||
|
, color: E.str $ "white"
|
||||||
|
, boxShadow: E.str "0 1px 8px rgba(0,0,0,0.5)"
|
||||||
|
, borderRadius: E.str "12px"
|
||||||
|
}
|
||||||
|
|
||||||
|
popperCss =
|
||||||
|
E.css
|
||||||
|
{ "&[data-popper-placement^='top'] > * > .popper-arrow":
|
||||||
|
nest { bottom: E.str "-4px" }
|
||||||
|
, "&[data-popper-placement^='bottom'] > * > .popper-arrow":
|
||||||
|
nest { top: E.str "-4px" }
|
||||||
|
, "&[data-popper-placement^='left'] > * > .popper-arrow":
|
||||||
|
nest { right: E.str "-4px" }
|
||||||
|
, "&[data-popper-placement^='right'] > * > .popper-arrow":
|
||||||
|
nest { left: E.str "-4px" }
|
||||||
}
|
}
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
40
src/React/Basic/Popper/Types.purs
Normal file
40
src/React/Basic/Popper/Types.purs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
module React.Basic.Popper.Types where
|
||||||
|
|
||||||
|
import Foreign.Object (Object)
|
||||||
|
import React.Basic.DOM (CSS)
|
||||||
|
import Unsafe.Coerce (unsafeCoerce)
|
||||||
|
import Yoga.Prelude.View (NodeRef, null)
|
||||||
|
|
||||||
|
nullRef ∷ NodeRef
|
||||||
|
nullRef = unsafeCoerce null
|
||||||
|
|
||||||
|
type ReferenceElement =
|
||||||
|
NodeRef
|
||||||
|
|
||||||
|
type PopperElement =
|
||||||
|
NodeRef
|
||||||
|
|
||||||
|
type ArrowElement =
|
||||||
|
NodeRef
|
||||||
|
|
||||||
|
type DataAttributes =
|
||||||
|
{ popper ∷ Object String, arrow ∷ Object String }
|
||||||
|
|
||||||
|
type Styles =
|
||||||
|
{ popper ∷ CSS, arrow ∷ CSS }
|
||||||
|
|
||||||
|
type PopperData =
|
||||||
|
{ styles ∷ Styles, attributes ∷ DataAttributes }
|
||||||
|
|
||||||
|
foreign import data Modifier ∷ Type
|
||||||
|
|
||||||
|
modifierArrow ∷ ArrowElement -> Modifier
|
||||||
|
modifierArrow element = unsafeCoerce { name: "arrow", options: { element } }
|
||||||
|
|
||||||
|
modifierOffset ∷ { x ∷ Number, y ∷ Number } -> Modifier
|
||||||
|
modifierOffset { x, y } = unsafeCoerce { name: "offset", options: { offset: [ x, y ] } }
|
||||||
|
|
||||||
|
type Options =
|
||||||
|
( modifiers ∷ Array Modifier
|
||||||
|
, strategy ∷ String
|
||||||
|
)
|
@ -21,7 +21,7 @@ codeInput props = styles <>? cast props.css
|
|||||||
, background: str colour.inputBackground
|
, background: str colour.inputBackground
|
||||||
, border: str $ i "solid 1px " colour.inputBorder
|
, border: str $ i "solid 1px " colour.inputBorder
|
||||||
, borderRadius: str "var(--s-2)"
|
, borderRadius: str "var(--s-2)"
|
||||||
, fontFamily: str "var(--monoFont)"
|
, fontFamily: str "var(--mono-font)"
|
||||||
, fontSize: str "var(--s0)"
|
, fontSize: str "var(--s0)"
|
||||||
, lineHeight: str "var(--s0)"
|
, lineHeight: str "var(--s0)"
|
||||||
, width: str $ i "calc(" (cast props.maxLength ?|| 10) "ch + 4.3 * var(--s-5))"
|
, width: str $ i "calc(" (cast props.maxLength ?|| 10) "ch + 4.3 * var(--s-5))"
|
||||||
|
5
src/Yoga/Block/Atom/Icon.purs
Normal file
5
src/Yoga/Block/Atom/Icon.purs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module Yoga.Block.Atom.Icon
|
||||||
|
( module Yoga.Block.Atom.Icon.View
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Yoga.Block.Atom.Icon.View (component, Props)
|
37
src/Yoga/Block/Atom/Icon/Story.purs
Normal file
37
src/Yoga/Block/Atom/Icon/Story.purs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
module Yoga.Block.Atom.Icon.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 Yoga.Block.Atom.Icon as Icon
|
||||||
|
import Yoga.Block.Container.Style as Styles
|
||||||
|
import Yoga.Block.Icon.SVG as SVGIcon
|
||||||
|
|
||||||
|
default ∷
|
||||||
|
{ decorators ∷ Array (Effect JSX -> JSX)
|
||||||
|
, title ∷ String
|
||||||
|
}
|
||||||
|
default =
|
||||||
|
{ title: "Atom/Icon"
|
||||||
|
, decorators:
|
||||||
|
[ \storyFn ->
|
||||||
|
R.div_
|
||||||
|
[ element E.global { styles: Styles.global }
|
||||||
|
, unsafePerformEffect storyFn
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
icon ∷ Effect JSX
|
||||||
|
icon = do
|
||||||
|
pure
|
||||||
|
$ fragment
|
||||||
|
[ R.div_
|
||||||
|
[ R.h2_ [ R.text "Icon" ]
|
||||||
|
, element Icon.component { icon: SVGIcon.on }
|
||||||
|
, element Icon.component { icon: SVGIcon.off }
|
||||||
|
]
|
||||||
|
]
|
27
src/Yoga/Block/Atom/Icon/Style.purs
Normal file
27
src/Yoga/Block/Atom/Icon/Style.purs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
module Yoga.Block.Atom.Icon.Style where
|
||||||
|
|
||||||
|
import Yoga.Prelude.Style
|
||||||
|
import Yoga.Block.Container.Style (colour)
|
||||||
|
|
||||||
|
type Props f r =
|
||||||
|
( css ∷ f Style
|
||||||
|
, colour ∷ f StyleProperty
|
||||||
|
, stroke ∷ f StyleProperty
|
||||||
|
, fill ∷ f StyleProperty
|
||||||
|
, size ∷ f StyleProperty
|
||||||
|
, width ∷ f StyleProperty
|
||||||
|
, height ∷ f StyleProperty
|
||||||
|
| r
|
||||||
|
)
|
||||||
|
|
||||||
|
span ∷ ∀ r. { | Props OptionalProp r } -> Style
|
||||||
|
span props =
|
||||||
|
css
|
||||||
|
{ "--stroke-colour": (props.stroke <|> props.colour) ?|| (str colour.text)
|
||||||
|
, "--fill-colour": (props.fill <|> props.colour) ?|| (str "transparent")
|
||||||
|
, "& > svg":
|
||||||
|
nest
|
||||||
|
{ width: (props.width <|> props.size) ?|| (str "auto")
|
||||||
|
, height: (props.height <|> props.size) ?|| (str "1.2ch")
|
||||||
|
}
|
||||||
|
}
|
32
src/Yoga/Block/Atom/Icon/View.purs
Normal file
32
src/Yoga/Block/Atom/Icon/View.purs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
module Yoga.Block.Atom.Icon.View where
|
||||||
|
|
||||||
|
import Yoga.Prelude.View
|
||||||
|
import React.Basic.DOM as R
|
||||||
|
import Yoga.Block.Atom.Icon.Style as Style
|
||||||
|
|
||||||
|
type Props =
|
||||||
|
PropsF Id
|
||||||
|
|
||||||
|
type MandatoryProps r =
|
||||||
|
( icon ∷ JSX
|
||||||
|
| r
|
||||||
|
)
|
||||||
|
|
||||||
|
type PropsF f =
|
||||||
|
( className ∷ f String
|
||||||
|
| Style.Props f (MandatoryProps ())
|
||||||
|
)
|
||||||
|
|
||||||
|
component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | MandatoryProps p }
|
||||||
|
component = rawComponent
|
||||||
|
|
||||||
|
rawComponent ∷ ∀ p. ReactComponent { | p }
|
||||||
|
rawComponent =
|
||||||
|
mkForwardRefComponent "Yoga Icon" \(props ∷ { | PropsF OptionalProp }) ref -> React.do
|
||||||
|
pure
|
||||||
|
$ styled R.span'
|
||||||
|
{ className: "ry-icon" <>? props.className
|
||||||
|
, css: Style.span props
|
||||||
|
, ref
|
||||||
|
}
|
||||||
|
[ props.icon ]
|
5
src/Yoga/Block/Atom/Input.purs
Normal file
5
src/Yoga/Block/Atom/Input.purs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module Yoga.Block.Atom.Input
|
||||||
|
( module Yoga.Block.Atom.Input.View
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Yoga.Block.Atom.Input.View (component, Props)
|
56
src/Yoga/Block/Atom/Input/Story.purs
Normal file
56
src/Yoga/Block/Atom/Input/Story.purs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
module Yoga.Block.Atom.Input.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.Input as Input
|
||||||
|
import Yoga.Block.Container.Style as Styles
|
||||||
|
|
||||||
|
default ∷
|
||||||
|
{ decorators ∷ Array (Effect JSX -> JSX)
|
||||||
|
, title ∷ String
|
||||||
|
}
|
||||||
|
default =
|
||||||
|
{ title: "Atom/Input"
|
||||||
|
, decorators:
|
||||||
|
[ \storyFn ->
|
||||||
|
R.div_
|
||||||
|
[ element E.global { styles: Styles.global }
|
||||||
|
, unsafePerformEffect storyFn
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
input ∷ Effect JSX
|
||||||
|
input = do
|
||||||
|
pure
|
||||||
|
$ fragment
|
||||||
|
[ R.div_
|
||||||
|
[ R.h2_ [ R.text "Generic Input" ]
|
||||||
|
, element Input.component { value: "A Generic Input", onChange: handler_ mempty }
|
||||||
|
, R.h2_ [ R.text "Password" ]
|
||||||
|
, element Input.component { type: "password" }
|
||||||
|
, R.h2_ [ R.text "Text Input" ]
|
||||||
|
, element Input.component { type: "text", value: "Some text", onChange: handler_ mempty }
|
||||||
|
, R.h2_ [ R.text "Search Input" ]
|
||||||
|
, element Input.component { type: "search", value: "Search...", onChange: handler_ mempty }
|
||||||
|
, R.h2_ [ R.text "Button" ]
|
||||||
|
, element Input.component { type: "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" }
|
||||||
|
, R.h2_ [ R.text "Checkbox" ]
|
||||||
|
, element Input.component { type: "checkbox" }
|
||||||
|
, R.h2_ [ R.text "File" ]
|
||||||
|
, element Input.component { type: "file" }
|
||||||
|
, R.h2_ [ R.text "Image" ]
|
||||||
|
, element Input.component { type: "image" }
|
||||||
|
, R.h2_ [ R.text "Number" ]
|
||||||
|
, element Input.component { type: "number" }
|
||||||
|
]
|
||||||
|
]
|
91
src/Yoga/Block/Atom/Input/Style.purs
Normal file
91
src/Yoga/Block/Atom/Input/Style.purs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
module Yoga.Block.Atom.Input.Style where
|
||||||
|
|
||||||
|
import Yoga.Prelude.Style
|
||||||
|
import Yoga.Block.Container.Style (colour)
|
||||||
|
import Yoga.Prelude.Style as Color
|
||||||
|
|
||||||
|
type Props f r =
|
||||||
|
( css ∷ f Style
|
||||||
|
| r
|
||||||
|
)
|
||||||
|
|
||||||
|
leftIconSize ∷ StyleProperty
|
||||||
|
leftIconSize = var "--left-icon-size"
|
||||||
|
|
||||||
|
rightIconSize ∷ StyleProperty
|
||||||
|
rightIconSize = var "--right-icon-size"
|
||||||
|
|
||||||
|
leftIconStyle ∷ Style
|
||||||
|
leftIconStyle =
|
||||||
|
css
|
||||||
|
{ "--stroke-colour": str colour.interfaceTextDisabled
|
||||||
|
, marginTop: str "4px"
|
||||||
|
, marginLeft: str "-4px"
|
||||||
|
}
|
||||||
|
|
||||||
|
rightIconStyle ∷ Style
|
||||||
|
rightIconStyle =
|
||||||
|
css
|
||||||
|
{ "--stroke-colour": str colour.interfaceTextDisabled
|
||||||
|
, paddingTop: str "6px"
|
||||||
|
, marginRight: str "6px"
|
||||||
|
}
|
||||||
|
|
||||||
|
textWrapper ∷ ∀ r. { | Props OptionalProp r } -> Style
|
||||||
|
textWrapper props =
|
||||||
|
css
|
||||||
|
{ fontFamily: var "--main-font"
|
||||||
|
, boxSizing: borderBox
|
||||||
|
, backgroundColor: str $ colour.background07
|
||||||
|
, display: inlineFlex
|
||||||
|
, "--left-icon-size": var "--s0"
|
||||||
|
, "--right-icon-size": str "calc(var(--s0) * 1.2)"
|
||||||
|
, alignItems: center
|
||||||
|
, justifyContent: flexStart
|
||||||
|
, paddingLeft: var "--s-1"
|
||||||
|
, gap: var "--s-3"
|
||||||
|
, "--border-width": var "--s-5"
|
||||||
|
, border: str $ "var(--border-width) solid " <> colour.inputBorder
|
||||||
|
, borderRadius: var "--s-1"
|
||||||
|
, "&:focus-within":
|
||||||
|
nest
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
|
||||||
|
input ∷ ∀ r. { | Props OptionalProp r } -> Style
|
||||||
|
input props =
|
||||||
|
css
|
||||||
|
{ "&[type=text],&[type=search],&[type=password],&[type=number],&:not([type])":
|
||||||
|
nest
|
||||||
|
{ color: str colour.text
|
||||||
|
, background: str "transparent"
|
||||||
|
, alignSelf: stretch
|
||||||
|
, "--padding-top": str "var(--s-1)"
|
||||||
|
, "--padding-bottom": str "calc(var(--padding-top) * 0.85)"
|
||||||
|
, paddingTop: var "--padding-top"
|
||||||
|
, paddingBottom: var "--padding-bottom"
|
||||||
|
, paddingLeft: _0
|
||||||
|
, paddingRight: _0
|
||||||
|
-- , background: str colour.inputBackground
|
||||||
|
, border: none
|
||||||
|
}
|
||||||
|
, "&[type=search]":
|
||||||
|
nest
|
||||||
|
{ "&::-webkit-search-decoration, &::-webkit-search-cancel-button, &::-webkit-serch-results-button, &::-webkit-search-results-decoration":
|
||||||
|
nest
|
||||||
|
{ "WebkitAppearance": none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, "&:focus":
|
||||||
|
nest
|
||||||
|
{ outline: none
|
||||||
|
}
|
||||||
|
, "&[type=button], &[type=submit]":
|
||||||
|
nest
|
||||||
|
{ background: str colour.highlight
|
||||||
|
, color: str "white"
|
||||||
|
, boxShadow: str "0 1px 4px rgba(0,0,0,0.5)"
|
||||||
|
, borderColour: str colour.highlight
|
||||||
|
, height: str "auto"
|
||||||
|
}
|
||||||
|
}
|
142
src/Yoga/Block/Atom/Input/View.purs
Normal file
142
src/Yoga/Block/Atom/Input/View.purs
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
module Yoga.Block.Atom.Input.View where
|
||||||
|
|
||||||
|
import Yoga.Prelude.View
|
||||||
|
import Framer.Motion as M
|
||||||
|
import React.Basic.DOM (css)
|
||||||
|
import React.Basic.DOM as R
|
||||||
|
import React.Basic.DOM.SVG as SVG
|
||||||
|
import React.Basic.Hooks as React
|
||||||
|
import Record.Extra (pick)
|
||||||
|
import Unsafe.Coerce (unsafeCoerce)
|
||||||
|
import Yoga.Block.Atom.Icon as Icon
|
||||||
|
import Yoga.Block.Atom.Input.Style as Style
|
||||||
|
import Yoga.Block.Atom.Tooltip as Tooltip
|
||||||
|
import Yoga.Block.Icon.SVG as SVGIcon
|
||||||
|
|
||||||
|
type PropsF f =
|
||||||
|
( iconLeft ∷ f JSX
|
||||||
|
, iconRight ∷ f JSX
|
||||||
|
| Style.Props f InputProps
|
||||||
|
)
|
||||||
|
|
||||||
|
type Props =
|
||||||
|
PropsF Id
|
||||||
|
|
||||||
|
type PropsOptional =
|
||||||
|
PropsF OptionalProp
|
||||||
|
|
||||||
|
component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
|
||||||
|
component = rawComponent
|
||||||
|
|
||||||
|
mkLeftIcon ∷ JSX -> JSX
|
||||||
|
mkLeftIcon icon =
|
||||||
|
styledLeaf
|
||||||
|
Icon.component
|
||||||
|
{ size: Style.leftIconSize
|
||||||
|
, className: "ry-input-right-icon"
|
||||||
|
, css: Style.leftIconStyle
|
||||||
|
, icon
|
||||||
|
}
|
||||||
|
|
||||||
|
mkRightIcon ∷ JSX -> JSX
|
||||||
|
mkRightIcon icon =
|
||||||
|
styledLeaf Icon.component
|
||||||
|
{ size: Style.rightIconSize
|
||||||
|
, className: "ry-input-left-icon"
|
||||||
|
, css: Style.rightIconStyle
|
||||||
|
, icon
|
||||||
|
}
|
||||||
|
|
||||||
|
rawComponent ∷ ∀ p. ReactComponent { | p }
|
||||||
|
rawComponent =
|
||||||
|
mkForwardRefComponent "Input" do
|
||||||
|
\(props ∷ { | PropsOptional }) ref -> React.do
|
||||||
|
let
|
||||||
|
iconLeft =
|
||||||
|
props.iconLeft
|
||||||
|
?|| if (((cast props.type) ?|| "") == "search") then mkLeftIcon SVGIcon.magnifyingGlass else mempty
|
||||||
|
iconRight =
|
||||||
|
props.iconRight
|
||||||
|
?|| if (((cast props.type) ?|| "") == "password") then mkRightIcon SVGIcon.eyeOpen else mempty
|
||||||
|
pure
|
||||||
|
$ case props.type # cast # opToMaybe of
|
||||||
|
Just "password" -> el_ password props
|
||||||
|
_ ->
|
||||||
|
styled R.div'
|
||||||
|
{ className: "ry-input-wrapper"
|
||||||
|
, css: Style.textWrapper props
|
||||||
|
}
|
||||||
|
[ iconLeft
|
||||||
|
, emotionInput
|
||||||
|
ref
|
||||||
|
props
|
||||||
|
{ className: "ry-input"
|
||||||
|
, css: Style.input props
|
||||||
|
}
|
||||||
|
, iconRight
|
||||||
|
]
|
||||||
|
|
||||||
|
password ∷ ∀ p. ReactComponent { | p }
|
||||||
|
password =
|
||||||
|
mkForwardRefComponent "Password" do
|
||||||
|
\(props ∷ { | PropsOptional }) ref -> React.do
|
||||||
|
hidePassword /\ modifyHidePassword <- useState true
|
||||||
|
let
|
||||||
|
eyeCon =
|
||||||
|
el_ Tooltip.component
|
||||||
|
{ target:
|
||||||
|
el R.div'
|
||||||
|
{ onClick: handler preventDefault \_ -> modifyHidePassword not
|
||||||
|
}
|
||||||
|
[ el M.animatePresence
|
||||||
|
{ exitBeforeEnter: true
|
||||||
|
}
|
||||||
|
[ if hidePassword then
|
||||||
|
el M.div
|
||||||
|
{ key: "eyeOpen"
|
||||||
|
, initial: M.initial $ css { scaleY: 0 }
|
||||||
|
, animate: M.animate $ css { scaleY: 1 }
|
||||||
|
, exit: M.exit $ css { scaleY: 0.9 }
|
||||||
|
, transition: M.transition { duration: 0.15 }
|
||||||
|
}
|
||||||
|
[ styledLeaf Icon.component
|
||||||
|
{ size: Style.rightIconSize
|
||||||
|
, className: "ry-input-left-icon"
|
||||||
|
, css: Style.rightIconStyle
|
||||||
|
, icon: SVGIcon.eyeOpen
|
||||||
|
}
|
||||||
|
]
|
||||||
|
else
|
||||||
|
el M.div
|
||||||
|
{ key: "eyeClosed"
|
||||||
|
, initial: M.initial $ css { scaleY: 0.0 }
|
||||||
|
, animate: M.animate $ css { scaleY: 1 }
|
||||||
|
, exit: M.exit $ css { scaleY: 0.9 }
|
||||||
|
, transition: M.transition { duration: 0.15 }
|
||||||
|
}
|
||||||
|
[ styledLeaf Icon.component
|
||||||
|
{ size: Style.rightIconSize
|
||||||
|
, className: "ry-input-left-icon"
|
||||||
|
, css: Style.rightIconStyle
|
||||||
|
, icon: SVGIcon.eyeClosed
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, theTip: R.text if hidePassword then "Show password" else "Hide password"
|
||||||
|
}
|
||||||
|
let iconRight = props.iconRight ?|| eyeCon
|
||||||
|
pure
|
||||||
|
$ styled R.div'
|
||||||
|
{ className: "ry-input-wrapper"
|
||||||
|
, css: Style.textWrapper props
|
||||||
|
}
|
||||||
|
[ emotionInput
|
||||||
|
ref
|
||||||
|
props
|
||||||
|
{ className: "ry-input"
|
||||||
|
, css: Style.input props
|
||||||
|
, type: if hidePassword then "password" else "text"
|
||||||
|
}
|
||||||
|
, iconRight
|
||||||
|
]
|
@ -6,8 +6,6 @@ import Yoga.Block.Container.Style (colour)
|
|||||||
|
|
||||||
type Props f r =
|
type Props f r =
|
||||||
( css ∷ f Style
|
( css ∷ f Style
|
||||||
, space ∷ f StyleProperty
|
|
||||||
, splitAfter ∷ f Int
|
|
||||||
| r
|
| r
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
module Yoga.Block.Atom.Range.View (component, Props, PropsF) where
|
module Yoga.Block.Atom.Range.View (component, Props, PropsF) where
|
||||||
|
|
||||||
import Yoga.Prelude.View
|
import Yoga.Prelude.View
|
||||||
import Yoga.Block.Atom.Range.Style as Style
|
|
||||||
import Data.Int as Int
|
import Data.Int as Int
|
||||||
import Foreign.Object as Object
|
import Foreign.Object as Object
|
||||||
|
import Framer.Motion as M
|
||||||
import React.Basic.DOM (css)
|
import React.Basic.DOM (css)
|
||||||
import React.Basic.DOM as R
|
import React.Basic.DOM as R
|
||||||
import React.Basic.DOM.Events as Event
|
import React.Basic.DOM.Events as Event
|
||||||
import React.Basic.Hooks as React
|
import React.Basic.Hooks as React
|
||||||
|
import Yoga.Block.Atom.Range.Style as Style
|
||||||
|
import Yoga.Block.Atom.Tooltip as Tooltip
|
||||||
|
|
||||||
type PropsF f =
|
type PropsF f =
|
||||||
( className ∷ f String
|
( className ∷ f String
|
||||||
@ -58,11 +60,11 @@ rawComponent =
|
|||||||
{ className: "ry-range-focus-circle"
|
{ className: "ry-range-focus-circle"
|
||||||
, css: Style.focusCircle
|
, css: Style.focusCircle
|
||||||
}
|
}
|
||||||
, emotionInput ref (props { max = show max, min = show min, value = show value })
|
, emotionInput
|
||||||
|
ref
|
||||||
|
(props { max = show max, min = show min, value = show value })
|
||||||
{ className: "ry-range-thumb " <>? props.className
|
{ className: "ry-range-thumb " <>? props.className
|
||||||
, css: Style.range props <> guard props.disabled Style.inputDisabled <>? props.css
|
, css: Style.range props <> guard props.disabled Style.inputDisabled <>? props.css
|
||||||
, style: props.style
|
|
||||||
, value: show value
|
|
||||||
, type: "range"
|
, type: "range"
|
||||||
, onChange: handler Event.targetValue ((_ >>= Int.fromString) >>> (foldMap setValue))
|
, onChange: handler Event.targetValue ((_ >>= Int.fromString) >>> (foldMap setValue))
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ module Yoga.Block.Atom.Toggle.Spec where
|
|||||||
|
|
||||||
import Yoga.Prelude.Spec
|
import Yoga.Prelude.Spec
|
||||||
import Yoga.Block.Atom.Toggle as Toggle
|
import Yoga.Block.Atom.Toggle as Toggle
|
||||||
|
import Yoga.Block.Atom.Toggle.Types (TogglePosition(..))
|
||||||
|
|
||||||
spec ∷ Spec Unit
|
spec ∷ Spec Unit
|
||||||
spec =
|
spec =
|
||||||
@ -10,6 +11,6 @@ spec =
|
|||||||
it "renders without errors" do
|
it "renders without errors" do
|
||||||
void
|
void
|
||||||
$ renderComponent Toggle.component
|
$ renderComponent Toggle.component
|
||||||
{ value: true
|
{ togglePosition: ToggleIsLeft
|
||||||
, onToggle: mempty
|
, setTogglePosition: mempty
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import React.Basic.DOM as R
|
|||||||
import React.Basic.Hooks as React
|
import React.Basic.Hooks as React
|
||||||
import Yoga.Block as Block
|
import Yoga.Block as Block
|
||||||
import Yoga.Block.Atom.Toggle as Toggle
|
import Yoga.Block.Atom.Toggle as Toggle
|
||||||
|
import Yoga.Block.Atom.Toggle.Types (TogglePosition(..))
|
||||||
import Yoga.Block.Container.Style (DarkOrLightMode(..))
|
import Yoga.Block.Container.Style (DarkOrLightMode(..))
|
||||||
|
|
||||||
default ∷
|
default ∷
|
||||||
@ -35,30 +36,32 @@ toggle = do
|
|||||||
where
|
where
|
||||||
mkBasicExample =
|
mkBasicExample =
|
||||||
React.reactComponent "Toggle example" \p -> React.do
|
React.reactComponent "Toggle example" \p -> React.do
|
||||||
isOn /\ turnOnOrOff <- React.useState' false
|
togglePosition /\ setTogglePosition <- React.useState' ToggleIsRight
|
||||||
pure
|
pure
|
||||||
$ element Toggle.component
|
$ element Toggle.component
|
||||||
{ value: isOn
|
{ togglePosition
|
||||||
, onToggle: turnOnOrOff
|
, setTogglePosition
|
||||||
}
|
}
|
||||||
|
|
||||||
mkDarkLightToggle =
|
mkDarkLightToggle =
|
||||||
React.reactComponent "Toggle dark night example" \p -> React.do
|
React.reactComponent "Toggle dark night example" \p -> React.do
|
||||||
isOn /\ turnOnOrOff <- React.useState' false
|
togglePosition /\ setTogglePosition <- React.useState' ToggleIsLeft
|
||||||
theme /\ setTheme <- React.useState' Nothing
|
theme /\ setTheme <- React.useState' Nothing
|
||||||
let
|
let
|
||||||
content =
|
content =
|
||||||
element Toggle.component
|
element Toggle.component
|
||||||
{ value: isOn
|
{ togglePosition: togglePosition
|
||||||
, onToggle:
|
, setTogglePosition:
|
||||||
\b -> do
|
\newTogglePosition -> do
|
||||||
turnOnOrOff b
|
setTogglePosition newTogglePosition
|
||||||
setTheme (Just if b then DarkMode else LightMode)
|
setTheme case newTogglePosition of
|
||||||
, on: R.text "🌒"
|
ToggleIsRight -> Just DarkMode
|
||||||
, off: R.text "🌞"
|
ToggleIsLeft -> Just LightMode
|
||||||
, backgroundOn:
|
, left: R.text "🌒"
|
||||||
Color.hsl 205.0 1.0 0.93
|
, right: R.text "🌞"
|
||||||
, backgroundOff:
|
, backgroundLeft:
|
||||||
|
Color.hsl 205.0 1.0 0.83
|
||||||
|
, backgroundRight:
|
||||||
Color.hsl 260.0 0.7 0.45
|
Color.hsl 260.0 0.7 0.45
|
||||||
}
|
}
|
||||||
pure
|
pure
|
||||||
|
@ -5,8 +5,8 @@ import Yoga.Block.Container.Style (colour)
|
|||||||
|
|
||||||
type Props f r =
|
type Props f r =
|
||||||
( css ∷ f Style
|
( css ∷ f Style
|
||||||
, backgroundOn ∷ f Color
|
, backgroundLeft ∷ f Color
|
||||||
, backgroundOff ∷ f Color
|
, backgroundRight ∷ f Color
|
||||||
| r
|
| r
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,17 +23,17 @@ button =
|
|||||||
, padding: _0
|
, padding: _0
|
||||||
}
|
}
|
||||||
|
|
||||||
theToggle ∷ ∀ p. { | Props OptionalProp p } -> Style
|
theToggle ∷ Style
|
||||||
theToggle props =
|
theToggle =
|
||||||
css
|
css
|
||||||
{ width: var "--s2"
|
{ width: str "calc(var(--s2) * 0.8)"
|
||||||
, height: var "--s2"
|
, height: str "calc(var(--s2) * 0.8)"
|
||||||
, background: str $ colour.interfaceBackground
|
, background: str $ colour.interfaceBackground
|
||||||
, border: none
|
, border: none
|
||||||
, borderRadius: str $ "calc(var(--s2) / 2)"
|
, borderRadius: str $ "calc(var(--s2) / 2)"
|
||||||
, position: absolute
|
, position: absolute
|
||||||
, top: str "-1px"
|
, top: str "3px"
|
||||||
, left: _0
|
, left: str "3px"
|
||||||
, margin: _0
|
, margin: _0
|
||||||
, boxShadow: str "0 0.5px 3px rgba(0,0,0,0.50)"
|
, boxShadow: str "0 0.5px 3px rgba(0,0,0,0.50)"
|
||||||
}
|
}
|
||||||
@ -46,25 +46,33 @@ toggleTextContainer =
|
|||||||
, fontWeight: str "bold"
|
, fontWeight: str "bold"
|
||||||
, position: absolute
|
, position: absolute
|
||||||
, top: _0
|
, top: _0
|
||||||
|
, fontSize: str "calc(0.6 * var(--s1))"
|
||||||
, lineHeight: var "--s2"
|
, lineHeight: var "--s2"
|
||||||
, height: var "--s2"
|
, height: var "--s2"
|
||||||
, display: flex
|
, display: flex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
successTextColour ∷ StyleProperty
|
||||||
|
successTextColour = str colour.successText
|
||||||
|
|
||||||
|
disabledTextColour ∷ StyleProperty
|
||||||
|
disabledTextColour = str colour.interfaceTextDisabled
|
||||||
|
|
||||||
toggleText ∷ Style
|
toggleText ∷ Style
|
||||||
toggleText =
|
toggleText =
|
||||||
css
|
css
|
||||||
{ textAlign: str "left"
|
{ textAlign: str "left"
|
||||||
, margin: _0
|
, margin: _0
|
||||||
|
, padding: _0
|
||||||
, width: str "50%"
|
, width: str "50%"
|
||||||
, height: str "100%"
|
, height: str "100%"
|
||||||
, display: flex
|
, display: flex
|
||||||
, justifyContent: center
|
, justifyContent: center
|
||||||
, alignItems: center
|
, alignItems: center
|
||||||
, color: str colour.interfaceTextDisabled
|
, color: disabledTextColour
|
||||||
, "&:first-child":
|
, "& > *":
|
||||||
nest
|
nest
|
||||||
{ color: str colour.successText
|
{ color: successTextColour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
src/Yoga/Block/Atom/Toggle/Types.purs
Normal file
19
src/Yoga/Block/Atom/Toggle/Types.purs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
module Yoga.Block.Atom.Toggle.Types where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
data TogglePosition
|
||||||
|
= ToggleIsLeft
|
||||||
|
| ToggleIsRight
|
||||||
|
|
||||||
|
derive instance eqTogglePosition ∷ Eq TogglePosition
|
||||||
|
|
||||||
|
instance showTogglePosition ∷ Show TogglePosition where
|
||||||
|
show = case _ of
|
||||||
|
ToggleIsLeft -> "ToggleIsLeft"
|
||||||
|
ToggleIsRight -> "ToggleIsRight"
|
||||||
|
|
||||||
|
flipToggle ∷ TogglePosition -> TogglePosition
|
||||||
|
flipToggle = case _ of
|
||||||
|
ToggleIsLeft -> ToggleIsRight
|
||||||
|
ToggleIsRight -> ToggleIsLeft
|
@ -3,26 +3,33 @@ module Yoga.Block.Atom.Toggle.View (component, MandatoryProps, Props, PropsF) wh
|
|||||||
import Yoga.Prelude.View
|
import Yoga.Prelude.View
|
||||||
import Color as Color
|
import Color as Color
|
||||||
import Data.Interpolate (i)
|
import Data.Interpolate (i)
|
||||||
|
import Data.Maybe (isNothing)
|
||||||
import Effect.Class.Console as Console
|
import Effect.Class.Console as Console
|
||||||
|
import Effect.Unsafe (unsafePerformEffect)
|
||||||
import Foreign.Object as Object
|
import Foreign.Object as Object
|
||||||
import Framer.Motion as Motion
|
import Framer.Motion as Motion
|
||||||
|
import Partial.Unsafe (unsafeCrashWith)
|
||||||
import React.Basic.DOM (css)
|
import React.Basic.DOM (css)
|
||||||
import React.Basic.DOM as R
|
import React.Basic.DOM as R
|
||||||
import React.Basic.Emotion as Emotion
|
import React.Basic.Emotion as Emotion
|
||||||
|
import React.Basic.Hooks (reactComponent)
|
||||||
import React.Basic.Hooks as React
|
import React.Basic.Hooks as React
|
||||||
|
import Yoga.Block.Atom.Icon as Icon
|
||||||
import Yoga.Block.Atom.Toggle.Style as Style
|
import Yoga.Block.Atom.Toggle.Style as Style
|
||||||
|
import Yoga.Block.Atom.Toggle.Types (TogglePosition(..), flipToggle)
|
||||||
import Yoga.Block.Container.Style (colour)
|
import Yoga.Block.Container.Style (colour)
|
||||||
|
import Yoga.Block.Icon.SVG as SVGIcon
|
||||||
|
|
||||||
type PropsF f =
|
type PropsF f =
|
||||||
( className ∷ f String
|
( className ∷ f String
|
||||||
, on ∷ f JSX
|
, left ∷ f JSX
|
||||||
, off ∷ f JSX
|
, right ∷ f JSX
|
||||||
| Style.Props f (MandatoryProps InputProps)
|
| Style.Props f (MandatoryProps InputProps)
|
||||||
)
|
)
|
||||||
|
|
||||||
type MandatoryProps r =
|
type MandatoryProps r =
|
||||||
( value ∷ Boolean
|
( togglePosition ∷ TogglePosition
|
||||||
, onToggle ∷ Boolean -> Effect Unit
|
, setTogglePosition ∷ TogglePosition -> Effect Unit
|
||||||
| r
|
| r
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,7 +39,7 @@ data TappingState
|
|||||||
|
|
||||||
data DragState
|
data DragState
|
||||||
= NotDragging
|
= NotDragging
|
||||||
| Dragging { startX ∷ Number }
|
| Dragging { startX ∷ Number, currentX ∷ Number }
|
||||||
| DragDone { startX ∷ Number, endX ∷ Number }
|
| DragDone { startX ∷ Number, endX ∷ Number }
|
||||||
|
|
||||||
derive instance eqDragState ∷ Eq DragState
|
derive instance eqDragState ∷ Eq DragState
|
||||||
@ -40,8 +47,8 @@ derive instance eqDragState ∷ Eq DragState
|
|||||||
instance showDragState ∷ Show DragState where
|
instance showDragState ∷ Show DragState where
|
||||||
show = case _ of
|
show = case _ of
|
||||||
NotDragging -> "NotDragging"
|
NotDragging -> "NotDragging"
|
||||||
Dragging x -> "Dragging " <> (show x)
|
Dragging x -> "Dragging " <> show x
|
||||||
DragDone x -> "DragDone " <> (show x)
|
DragDone x -> "DragDone " <> show x
|
||||||
|
|
||||||
type Props =
|
type Props =
|
||||||
PropsF Id
|
PropsF Id
|
||||||
@ -57,147 +64,213 @@ rawComponent =
|
|||||||
mkForwardRefComponent "Toggle" do
|
mkForwardRefComponent "Toggle" do
|
||||||
\(props ∷ { | PropsOptional }) ref -> React.do
|
\(props ∷ { | PropsOptional }) ref -> React.do
|
||||||
let disabled = props.disabled
|
let disabled = props.disabled
|
||||||
tapState <- useRef TapNotAllowed
|
|
||||||
dragState /\ setDragState <- React.useState' NotDragging
|
|
||||||
maxLeft /\ setMaxLeft <- useState' 0.0
|
|
||||||
buttonRef <- useRef null
|
buttonRef <- useRef null
|
||||||
toggleRef <- useRef null
|
toggleRef <- useRef null
|
||||||
leftState /\ setLeftState <- React.useState' 0.0
|
tapState <- useRef TapNotAllowed
|
||||||
let
|
dragState /\ setDragState <- React.useState' NotDragging
|
||||||
getWidth aRef = do
|
|
||||||
bbox <- getBoundingBoxFromRef aRef
|
|
||||||
pure $ bbox <#> _.width # fromMaybe 0.0
|
|
||||||
buttonWidth = getWidth buttonRef
|
|
||||||
toggleWidth = getWidth toggleRef
|
|
||||||
useLayoutEffectAlways do
|
|
||||||
when (maxLeft == 0.0) do
|
|
||||||
bw <- buttonWidth
|
|
||||||
tw <- toggleWidth
|
|
||||||
setMaxLeft (bw - tw)
|
|
||||||
mempty
|
|
||||||
let
|
|
||||||
toggleVariants =
|
|
||||||
{ off: { x: 0.0 }
|
|
||||||
, on: { x: maxLeft }
|
|
||||||
}
|
|
||||||
toggleVariant = Motion.makeVariantLabels toggleVariants
|
|
||||||
buttonVariants =
|
|
||||||
{ off: { backgroundColor: (Emotion.str <<< Color.cssStringRGBA <$> props.backgroundOn) ?|| Emotion.str colour.inputBackground }
|
|
||||||
, on: { backgroundColor: (Emotion.str <<< Color.cssStringRGBA <$> props.backgroundOff) ?|| Emotion.str colour.success }
|
|
||||||
}
|
|
||||||
buttonVariant = Motion.makeVariantLabels buttonVariants
|
|
||||||
hasFocus /\ setHasFocus <- useState' false
|
|
||||||
useEffect dragState do
|
useEffect dragState do
|
||||||
case dragState of
|
case dragState of
|
||||||
NotDragging -> mempty
|
NotDragging -> mempty
|
||||||
Dragging { startX } -> writeRef tapState TapNotAllowed
|
Dragging { startX, currentX } -> do
|
||||||
|
writeRef tapState TapNotAllowed
|
||||||
DragDone { startX, endX } -> do
|
DragDone { startX, endX } -> do
|
||||||
maybeBbox <- getBoundingBoxFromRef buttonRef
|
maybeBbox <- getBoundingBoxFromRef buttonRef
|
||||||
for_ maybeBbox \bbox -> do
|
for_ maybeBbox \bbox -> do
|
||||||
if endX - startX <= (bbox.left - startX) + (bbox.width / 2.0) then do
|
if endX - startX <= (bbox.left - startX) + (bbox.width / 2.0) then do
|
||||||
props.onToggle false
|
props.setTogglePosition ToggleIsLeft
|
||||||
else do
|
else do
|
||||||
props.onToggle true
|
props.setTogglePosition ToggleIsRight
|
||||||
mempty
|
mempty
|
||||||
pure
|
let
|
||||||
$ styled Motion.button
|
buttonVariants =
|
||||||
|
{ left: { backgroundColor: (Emotion.str <<< Color.cssStringRGBA <$> props.backgroundLeft) ?|| Emotion.str colour.inputBackground }
|
||||||
|
, right: { backgroundColor: (Emotion.str <<< Color.cssStringRGBA <$> props.backgroundRight) ?|| Emotion.str colour.success }
|
||||||
|
}
|
||||||
|
buttonVariant = Motion.makeVariantLabels buttonVariants
|
||||||
|
-- components
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
container
|
||||||
|
[ animateTextPresence
|
||||||
|
[ textContainer
|
||||||
|
[ textOnContainer
|
||||||
|
[ guard (props.togglePosition == ToggleIsRight)
|
||||||
|
$ textOn
|
||||||
|
[ props.left
|
||||||
|
?|| el_ Icon.component { icon: SVGIcon.on, stroke: Style.successTextColour }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, textOffContainer
|
||||||
|
[ guard (props.togglePosition == ToggleIsLeft)
|
||||||
|
$ textOff
|
||||||
|
[ props.right
|
||||||
|
?|| el_ Icon.component { icon: SVGIcon.off, stroke: Style.disabledTextColour }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, toggle
|
||||||
|
]
|
||||||
|
container =
|
||||||
|
styled Motion.button
|
||||||
{ className: "ry-toggle"
|
{ className: "ry-toggle"
|
||||||
, css: Style.button <> guard props.disabled Style.inputDisabled
|
, css: Style.button
|
||||||
, onFocus: handler_ $ setHasFocus true
|
|
||||||
, onBlur: handler_ $ setHasFocus false
|
|
||||||
, transition: Motion.transition { type: "tween", duration: 0.33, ease: "easeOut" }
|
, transition: Motion.transition { type: "tween", duration: 0.33, ease: "easeOut" }
|
||||||
, variants: Motion.variants buttonVariants
|
, variants: Motion.variants buttonVariants
|
||||||
, animate: Motion.animate if props.value then buttonVariant.on else buttonVariant.off
|
, animate:
|
||||||
, value: show props.value
|
Motion.animate case props.togglePosition of
|
||||||
, onClick: handler preventDefault \_ -> props.onToggle (not props.value)
|
ToggleIsRight -> buttonVariant.right
|
||||||
|
ToggleIsLeft -> buttonVariant.left
|
||||||
|
, value: show props.togglePosition
|
||||||
|
, onClick: handler preventDefault \_ -> props.setTogglePosition (flipToggle props.togglePosition)
|
||||||
, style: props.style
|
, style: props.style
|
||||||
, _data: Object.singleton "testid" "toggle-testid"
|
, _data: Object.singleton "testid" "toggle-testid"
|
||||||
, role: "switch"
|
, role: "switch"
|
||||||
, _aria: Object.singleton "checked" "switch"
|
, _aria: Object.singleton "checked" "switch"
|
||||||
, ref: buttonRef
|
, ref: buttonRef
|
||||||
}
|
}
|
||||||
[ styled R.div'
|
textContainer =
|
||||||
|
styled R.div'
|
||||||
{ className: "ry-toggle-text"
|
{ className: "ry-toggle-text"
|
||||||
, css: Style.toggleTextContainer
|
, css: Style.toggleTextContainer
|
||||||
}
|
}
|
||||||
[ styled R.div'
|
textOnContainer =
|
||||||
|
styled R.div'
|
||||||
{ className: "ry-toggle-text-on"
|
{ className: "ry-toggle-text-on"
|
||||||
, css: Style.toggleText
|
, css: Style.toggleText
|
||||||
}
|
}
|
||||||
[ el Motion.animatePresence {}
|
textOffContainer =
|
||||||
[ guard (props.value)
|
styled R.div'
|
||||||
$ styled Motion.div
|
|
||||||
{ className: "ry-toggle-text-on-container"
|
|
||||||
, css: Style.toggleOnText
|
|
||||||
, key: "ry-toggle-text-on-container"
|
|
||||||
, initial: Motion.initial $ css { scale: 0, opacity: 0 }
|
|
||||||
, animate: Motion.animate $ css { scale: 1, opacity: 1 }
|
|
||||||
, exit: Motion.exit $ css { scale: 0, opacity: 0 }
|
|
||||||
}
|
|
||||||
[ props.on ?|| R.text "I" ]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
, styled R.div'
|
|
||||||
{ className: "ry-toggle-text-off"
|
{ className: "ry-toggle-text-off"
|
||||||
, css: Style.toggleText
|
, css: Style.toggleText
|
||||||
}
|
}
|
||||||
[ el Motion.animatePresence {}
|
textOn =
|
||||||
[ guard (not props.value)
|
el Motion.div
|
||||||
$ styled Motion.div
|
{ className: "ry-toggle-text-container"
|
||||||
{ className: "ry-toggle-text-on-container"
|
|
||||||
, css: Style.toggleOnText
|
|
||||||
, key: "ry-toggle-text-on-container"
|
, key: "ry-toggle-text-on-container"
|
||||||
, initial: Motion.initial $ css { scale: 0, opacity: 0 }
|
, initial: Motion.initial $ css { scale: 0, opacity: 0 }
|
||||||
, animate: Motion.animate $ css { scale: 1, opacity: 1 }
|
, animate: Motion.animate $ css { scale: 1, opacity: 1 }
|
||||||
, exit: Motion.exit $ css { scale: 0, opacity: 0 }
|
, exit: Motion.exit $ css { scale: 0, opacity: 0 }
|
||||||
}
|
}
|
||||||
[ props.off ?|| R.text "O" ]
|
textOff =
|
||||||
]
|
el Motion.div
|
||||||
]
|
{ className: "ry-toggle-text-container"
|
||||||
]
|
, key: "ry-toggle-text-off-container"
|
||||||
, styled Motion.div
|
, initial: Motion.initial $ css { scale: 0, opacity: 0 }
|
||||||
|
, animate: Motion.animate $ css { scale: 1, opacity: 1 }
|
||||||
|
, exit: Motion.exit $ css { scale: 0, opacity: 0 }
|
||||||
|
}
|
||||||
|
animateTextPresence = el Motion.animatePresence {}
|
||||||
|
toggle =
|
||||||
|
el_ toggleCircle
|
||||||
|
{ buttonRef
|
||||||
|
, toggleRef
|
||||||
|
, togglePosition: props.togglePosition
|
||||||
|
, setTogglePosition: props.setTogglePosition
|
||||||
|
, dragState
|
||||||
|
, setDragState
|
||||||
|
, tapState
|
||||||
|
}
|
||||||
|
pure result
|
||||||
|
|
||||||
|
toggleCircle ∷
|
||||||
|
ReactComponent
|
||||||
|
{ setTogglePosition ∷ TogglePosition -> Effect Unit
|
||||||
|
, toggleRef ∷ NodeRef
|
||||||
|
, buttonRef ∷ NodeRef
|
||||||
|
, togglePosition ∷ TogglePosition
|
||||||
|
, dragState ∷ DragState
|
||||||
|
, setDragState ∷ DragState -> Effect Unit
|
||||||
|
, tapState ∷ Ref TappingState
|
||||||
|
}
|
||||||
|
toggleCircle =
|
||||||
|
unsafePerformEffect
|
||||||
|
$ reactComponent "ToggleCircle" do
|
||||||
|
\( { togglePosition
|
||||||
|
, setTogglePosition
|
||||||
|
, toggleRef
|
||||||
|
, buttonRef
|
||||||
|
, dragState
|
||||||
|
, setDragState
|
||||||
|
, tapState
|
||||||
|
}
|
||||||
|
) -> React.do
|
||||||
|
maxLeft /\ setMaxLeft <- useState' Nothing
|
||||||
|
useEffectAlways do
|
||||||
|
when (maxLeft == Nothing) do
|
||||||
|
runMaybeT_ do
|
||||||
|
b <- getBoundingBoxFromRef buttonRef # MaybeT
|
||||||
|
t <- getBoundingBoxFromRef toggleRef # MaybeT
|
||||||
|
let ml = b.width - t.width - (2.0 * (t.left - b.left))
|
||||||
|
setMaxLeft (Just ml) # lift
|
||||||
|
mempty
|
||||||
|
let
|
||||||
|
toggleVariants =
|
||||||
|
{ left: { x: 0.0 }
|
||||||
|
, right: { x: maxLeft # fromMaybe 0.0 }
|
||||||
|
}
|
||||||
|
toggleVariant = Motion.makeVariantLabels toggleVariants
|
||||||
|
pure
|
||||||
|
$ styledLeaf Motion.div
|
||||||
{ className: "ry-toggle-toggle"
|
{ className: "ry-toggle-toggle"
|
||||||
, css: Style.theToggle props
|
|
||||||
, layout: Motion.layout true
|
, layout: Motion.layout true
|
||||||
, onClick: handler stopPropagation mempty
|
, onClick: handler stopPropagation mempty
|
||||||
|
, onTouchStart: handler stopPropagation mempty
|
||||||
|
, onTouchEnd: handler stopPropagation mempty
|
||||||
|
, css: Style.theToggle
|
||||||
, drag: Motion.drag "x"
|
, drag: Motion.drag "x"
|
||||||
, dragMomentum: Motion.dragMomentum false
|
, dragMomentum: Motion.dragMomentum false
|
||||||
|
, key: if isNothing maxLeft then "initialising" else "ready"
|
||||||
, dragElastic: Motion.dragElastic false
|
, dragElastic: Motion.dragElastic false
|
||||||
, dragConstraints:
|
, dragConstraints:
|
||||||
Motion.dragConstraints
|
Motion.dragConstraints
|
||||||
{ left: if props.value then negate maxLeft else zero
|
{ left:
|
||||||
, right: if props.value then zero else maxLeft
|
case togglePosition of
|
||||||
|
ToggleIsLeft -> zero
|
||||||
|
ToggleIsRight -> negate (maxLeft # fromMaybe 0.0)
|
||||||
|
, right:
|
||||||
|
case togglePosition of
|
||||||
|
ToggleIsRight -> zero
|
||||||
|
ToggleIsLeft -> maxLeft # fromMaybe 0.0
|
||||||
}
|
}
|
||||||
, variants: Motion.variants toggleVariants
|
, variants: Motion.variants toggleVariants
|
||||||
, transition: Motion.transition { type: "tween", duration: 0.33, ease: "easeOut" }
|
, transition: Motion.transition { type: "tween", duration: 0.33, ease: "easeOut" }
|
||||||
, whileTap: Motion.prop $ css { scale: 0.85, transition: { type: "tween", duration: 0.10, ease: "easeInOut" } }
|
, whileTap: Motion.prop $ css { scale: 1.1, transition: { type: "tween", duration: 0.10, ease: "easeInOut" } }
|
||||||
, onTapStart: Motion.onTapStart \_ _ -> writeRef tapState TapAllowed
|
, onTapStart: Motion.onTapStart \_ _ -> writeRef tapState TapAllowed
|
||||||
, onTap:
|
, onTap:
|
||||||
Motion.onTap \_ pi -> do
|
Motion.onTap \_ pi -> do
|
||||||
ts <- readRef tapState
|
ts <- readRef tapState
|
||||||
case ts of
|
case ts of
|
||||||
TapAllowed -> props.onToggle $ not props.value
|
TapAllowed -> setTogglePosition (flipToggle togglePosition)
|
||||||
_ -> mempty
|
_ -> mempty
|
||||||
mempty
|
mempty
|
||||||
, onTapCancel:
|
, onTapCancel:
|
||||||
Motion.onTapCancel \_ pi -> do
|
Motion.onTapCancel \_ pi -> do
|
||||||
writeRef tapState TapNotAllowed
|
writeRef tapState TapNotAllowed
|
||||||
mempty
|
mempty
|
||||||
, animate: Motion.animate if props.value then toggleVariant.on else toggleVariant.off
|
, initial: Motion.initial false
|
||||||
|
, animate:
|
||||||
|
Motion.animate case togglePosition of
|
||||||
|
ToggleIsLeft -> toggleVariant.left
|
||||||
|
ToggleIsRight -> toggleVariant.right
|
||||||
, onDragStart:
|
, onDragStart:
|
||||||
Motion.onDragStart \_ pi -> do
|
Motion.onDragStart \_ pi -> do
|
||||||
maybeBBox <- getBoundingBoxFromRef toggleRef
|
maybeBBox <- getBoundingBoxFromRef toggleRef
|
||||||
let x = maybeBBox <#> \bbox -> bbox.left + (bbox.width / 2.0)
|
let x = maybeBBox <#> \bbox -> bbox.left + (bbox.width / 2.0)
|
||||||
setDragState $ Dragging { startX: x # fromMaybe pi.point.x }
|
setDragState $ Dragging { startX: x # fromMaybe pi.point.x, currentX: pi.point.x }
|
||||||
|
, onDrag:
|
||||||
|
Motion.onDrag \_ pi -> do
|
||||||
|
case dragState of
|
||||||
|
Dragging { startX } -> do
|
||||||
|
setDragState $ Dragging { startX, currentX: pi.point.x }
|
||||||
|
other -> Console.warn $ i "Unexpected drag state " (show other) " in onDragEvent"
|
||||||
, onDragEnd:
|
, onDragEnd:
|
||||||
Motion.onDragEnd \_ pi -> do
|
Motion.onDragEnd \_ pi -> do
|
||||||
case dragState of
|
case dragState of
|
||||||
Dragging { startX } -> do
|
Dragging { startX } -> do
|
||||||
maybeBBox <- getBoundingBoxFromRef toggleRef
|
maybeBBox <- getBoundingBoxFromRef toggleRef
|
||||||
let x = maybeBBox <#> \bbox -> bbox.left + (bbox.width / 2.0)
|
let x = maybeBBox <#> \bbox -> bbox.left + (bbox.width / 2.0)
|
||||||
setDragState (DragDone { startX, endX: x # fromMaybe pi.point.x })
|
setDragState (DragDone { startX, endX: x # fromMaybe' \_ -> unsafeCrashWith "shit" })
|
||||||
other -> Console.warn $ i "Unexpected drag state " (show other) " in onDragEvent"
|
other -> Console.warn $ i "Unexpected drag state " (show other) " in onDragEvent"
|
||||||
, ref: toggleRef
|
, ref: toggleRef
|
||||||
}
|
}
|
||||||
[]
|
|
||||||
]
|
|
||||||
|
5
src/Yoga/Block/Atom/Tooltip.purs
Normal file
5
src/Yoga/Block/Atom/Tooltip.purs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module Yoga.Block.Atom.Tooltip
|
||||||
|
( module Yoga.Block.Atom.Tooltip.View
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Yoga.Block.Atom.Tooltip.View (component, Props)
|
16
src/Yoga/Block/Atom/Tooltip/Spec.purs
Normal file
16
src/Yoga/Block/Atom/Tooltip/Spec.purs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
module Yoga.Block.Atom.Tooltip.Spec where
|
||||||
|
|
||||||
|
import Yoga.Prelude.Spec
|
||||||
|
import React.Basic.DOM as R
|
||||||
|
import Yoga.Block.Atom.Tooltip as Tooltip
|
||||||
|
|
||||||
|
spec ∷ Spec Unit
|
||||||
|
spec =
|
||||||
|
after_ cleanup do
|
||||||
|
describe "The tooltip" do
|
||||||
|
it "renders without errors" do
|
||||||
|
void
|
||||||
|
$ renderComponent Tooltip.component
|
||||||
|
{ theTip: R.text "Tip"
|
||||||
|
, target: R.text "Target"
|
||||||
|
}
|
39
src/Yoga/Block/Atom/Tooltip/Story.purs
Normal file
39
src/Yoga/Block/Atom/Tooltip/Story.purs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
module Yoga.Block.Atom.Tooltip.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 Yoga (el)
|
||||||
|
import Yoga.Block.Atom.Tooltip as Tooltip
|
||||||
|
import Yoga.Block.Container.Style as Styles
|
||||||
|
|
||||||
|
default ∷
|
||||||
|
{ decorators ∷ Array (Effect JSX -> JSX)
|
||||||
|
, title ∷ String
|
||||||
|
}
|
||||||
|
default =
|
||||||
|
{ title: "Atom/Tooltip"
|
||||||
|
, decorators:
|
||||||
|
[ \storyFn ->
|
||||||
|
R.div_
|
||||||
|
[ element E.global { styles: Styles.global }
|
||||||
|
, unsafePerformEffect storyFn
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip ∷ Effect JSX
|
||||||
|
tooltip = do
|
||||||
|
pure
|
||||||
|
$ fragment
|
||||||
|
[ R.div_
|
||||||
|
[ R.h2_ [ R.text "Basics" ]
|
||||||
|
, element Tooltip.component
|
||||||
|
{ theTip: R.text "Hi"
|
||||||
|
, target: el R.button' {} [ R.text "Holzkop" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
57
src/Yoga/Block/Atom/Tooltip/Style.purs
Normal file
57
src/Yoga/Block/Atom/Tooltip/Style.purs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
module Yoga.Block.Atom.Tooltip.Style where
|
||||||
|
|
||||||
|
import Yoga.Prelude.Style
|
||||||
|
import Yoga.Block.Container.Style (colour)
|
||||||
|
|
||||||
|
type Props f r =
|
||||||
|
( css ∷ f Style
|
||||||
|
, backgroundColour ∷ f Color
|
||||||
|
| r
|
||||||
|
)
|
||||||
|
|
||||||
|
backgroundColour ∷ String
|
||||||
|
backgroundColour = colour.text
|
||||||
|
|
||||||
|
arrow ∷ ∀ r. { | Props OptionalProp r } -> Style
|
||||||
|
arrow props =
|
||||||
|
css
|
||||||
|
{ position: str "absolute"
|
||||||
|
, width: str "12px"
|
||||||
|
, height: str "12px"
|
||||||
|
, zIndex: str "0"
|
||||||
|
, "&::before":
|
||||||
|
nest
|
||||||
|
{ position: str "absolute"
|
||||||
|
, width: str "12px"
|
||||||
|
, height: str "12px"
|
||||||
|
, borderRadius: str "2px"
|
||||||
|
, content: str "''"
|
||||||
|
, transform: str "rotate(45deg)"
|
||||||
|
, background: str $ (cssStringRGBA <$> props.backgroundColour) ?|| backgroundColour
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content ∷ ∀ r. { | Props OptionalProp r } -> Style
|
||||||
|
content props =
|
||||||
|
css
|
||||||
|
{ background: str $ (cssStringRGBA <$> props.backgroundColour) ?|| backgroundColour
|
||||||
|
, minWidth: str "50px"
|
||||||
|
, padding: str "6px"
|
||||||
|
, zIndex: str "-1"
|
||||||
|
, color: str colour.background0
|
||||||
|
, boxShadow: str "0 1px 8px rgba(0,0,0,0.33)"
|
||||||
|
, borderRadius: var "--s-2"
|
||||||
|
}
|
||||||
|
|
||||||
|
popper ∷ Style
|
||||||
|
popper =
|
||||||
|
css
|
||||||
|
{ "&[data-popper-placement^='top'] > * > .popper-arrow":
|
||||||
|
nest { bottom: str "-4px" }
|
||||||
|
, "&[data-popper-placement^='bottom'] > * > .popper-arrow":
|
||||||
|
nest { top: str "-4px" }
|
||||||
|
, "&[data-popper-placement^='left'] > * > .popper-arrow":
|
||||||
|
nest { right: str "-4px" }
|
||||||
|
, "&[data-popper-placement^='right'] > * > .popper-arrow":
|
||||||
|
nest { left: str "-4px" }
|
||||||
|
}
|
129
src/Yoga/Block/Atom/Tooltip/View.purs
Normal file
129
src/Yoga/Block/Atom/Tooltip/View.purs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
module Yoga.Block.Atom.Tooltip.View (component, MandatoryProps, Props, PropsF) where
|
||||||
|
|
||||||
|
import Yoga.Prelude.View
|
||||||
|
import Debug.Trace (spy)
|
||||||
|
import Effect.Aff (Milliseconds(..), delay)
|
||||||
|
import Effect.Uncurried (mkEffectFn1)
|
||||||
|
import Framer.Motion as Motion
|
||||||
|
import React.Basic.DOM (css)
|
||||||
|
import React.Basic.DOM as R
|
||||||
|
import React.Basic.Hooks as React
|
||||||
|
import React.Basic.Hooks.Aff (useAff)
|
||||||
|
import React.Basic.Popper.Hook (usePopper)
|
||||||
|
import React.Basic.Popper.Types (modifierArrow, modifierOffset, nullRef)
|
||||||
|
import Unsafe.Coerce (unsafeCoerce)
|
||||||
|
import Yoga.Block.Atom.Tooltip.Style as Style
|
||||||
|
|
||||||
|
type PropsF f =
|
||||||
|
( className ∷ f String
|
||||||
|
, hideDelay ∷ f Milliseconds
|
||||||
|
| Style.Props f (MandatoryProps ())
|
||||||
|
)
|
||||||
|
|
||||||
|
type MandatoryProps r =
|
||||||
|
( theTip ∷ JSX
|
||||||
|
, target ∷ JSX
|
||||||
|
| r
|
||||||
|
)
|
||||||
|
|
||||||
|
type Props =
|
||||||
|
PropsF Id
|
||||||
|
|
||||||
|
type PropsOptional =
|
||||||
|
PropsF OptionalProp
|
||||||
|
|
||||||
|
component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | MandatoryProps p }
|
||||||
|
component = rawComponent
|
||||||
|
|
||||||
|
rawComponent ∷ ∀ p. ReactComponent (Record p)
|
||||||
|
rawComponent =
|
||||||
|
mkForwardRefComponent "Tooltip" do
|
||||||
|
\(props ∷ { | PropsOptional }) ref -> React.do
|
||||||
|
-- Hooks
|
||||||
|
referenceElement /\ setReferenceElement <- React.useState' nullRef
|
||||||
|
popperElement /\ setPopperElement <- React.useState' nullRef
|
||||||
|
arrowElement /\ setArrowElement <- React.useState' nullRef
|
||||||
|
{ styles, attributes } <-
|
||||||
|
usePopper referenceElement popperElement
|
||||||
|
{ modifiers:
|
||||||
|
[ modifierArrow arrowElement
|
||||||
|
, modifierOffset { x: 0.0, y: 12.0 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
visible /\ setVisible <- React.useState' false
|
||||||
|
touching /\ setTouching <- React.useState' false
|
||||||
|
hovering /\ setHovering <- React.useState' false
|
||||||
|
useAff hovering do
|
||||||
|
if hovering then
|
||||||
|
setVisible true # liftEffect
|
||||||
|
else do
|
||||||
|
delay (props.hideDelay ?|| (0.0 # Milliseconds))
|
||||||
|
setVisible false # liftEffect
|
||||||
|
useAff touching do
|
||||||
|
if touching then do
|
||||||
|
let _ = spy "sausage" touching
|
||||||
|
delay (1000.0 # Milliseconds)
|
||||||
|
setVisible true # liftEffect
|
||||||
|
else do
|
||||||
|
delay (props.hideDelay ?|| (450.0 # Milliseconds))
|
||||||
|
setVisible false # liftEffect
|
||||||
|
-- Handlers
|
||||||
|
let
|
||||||
|
hoveredIn = setHovering true
|
||||||
|
hoveredOut = setHovering false
|
||||||
|
touchStarted = setTouching true
|
||||||
|
touchEnded = setTouching false
|
||||||
|
-- Elements
|
||||||
|
let
|
||||||
|
result =
|
||||||
|
fragment
|
||||||
|
$ [ refElem
|
||||||
|
, popperEl
|
||||||
|
[ animatePresence
|
||||||
|
$ guard visible
|
||||||
|
[ content
|
||||||
|
[ props.theTip
|
||||||
|
, arrow
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
animatePresence = el Motion.animatePresence { initial: false }
|
||||||
|
content =
|
||||||
|
styled Motion.div
|
||||||
|
{ className: "popper-element-content"
|
||||||
|
, css: Style.content props
|
||||||
|
, initial: Motion.initial $ R.css { opacity: [ 1.0, 0.8, 0.0 ], scale: [ 1.0, 0.85 ] }
|
||||||
|
, animate: Motion.animate $ R.css { opacity: [ 0.0, 0.3, 1.0 ], scale: [ 0.0, 1.05, 1.0, 0.98, 1.01, 1.0 ] }
|
||||||
|
, exit: Motion.exit $ R.css { opacity: [ 1.0, 0.8, 0.0 ], scale: [ 1.0, 0.85 ] }
|
||||||
|
, transition: Motion.transition { duration: 0.2 }
|
||||||
|
, key: "container"
|
||||||
|
}
|
||||||
|
popperEl =
|
||||||
|
styled R.div'
|
||||||
|
{ className: "popper-element"
|
||||||
|
, css: Style.popper
|
||||||
|
, ref: unsafeCoerce (mkEffectFn1 setPopperElement)
|
||||||
|
, style: styles.popper
|
||||||
|
, _data: attributes.popper
|
||||||
|
}
|
||||||
|
arrow =
|
||||||
|
styledLeaf R.div'
|
||||||
|
{ className: "popper-arrow"
|
||||||
|
, id: "arrow"
|
||||||
|
, css: Style.arrow props
|
||||||
|
, ref: unsafeCoerce (mkEffectFn1 setArrowElement)
|
||||||
|
, style: styles.arrow
|
||||||
|
, _data: attributes.arrow
|
||||||
|
}
|
||||||
|
refElem =
|
||||||
|
element Motion.div
|
||||||
|
{ ref: unsafeCoerce (mkEffectFn1 setReferenceElement)
|
||||||
|
, style: css { display: "inline-block" }
|
||||||
|
, children: [ props.target ]
|
||||||
|
, onHoverStart: Motion.onHoverStart \_ _ -> hoveredIn
|
||||||
|
, onHoverEnd: Motion.onHoverEnd \_ _ -> hoveredOut
|
||||||
|
, onTouchStart: handler_ touchStarted
|
||||||
|
, onTouchEnd: handler_ touchEnded
|
||||||
|
}
|
||||||
|
pure result
|
@ -50,7 +50,7 @@ mkGlobal maybeMode =
|
|||||||
, body:
|
, body:
|
||||||
nested
|
nested
|
||||||
$ css
|
$ css
|
||||||
{ fontFamily: str "var(--mainFont)"
|
{ fontFamily: str "var(--main-font)"
|
||||||
, background: str colour.background0
|
, background: str colour.background0
|
||||||
, color: str colour.text
|
, color: str colour.text
|
||||||
, margin: str "0"
|
, margin: str "0"
|
||||||
@ -61,7 +61,7 @@ mkGlobal maybeMode =
|
|||||||
Just LightMode -> lightModeStyle
|
Just LightMode -> lightModeStyle
|
||||||
, "pre,code":
|
, "pre,code":
|
||||||
nest
|
nest
|
||||||
{ fontFamily: str "var(--monoFont)"
|
{ fontFamily: str "var(--mono-font)"
|
||||||
}
|
}
|
||||||
, "h1,h2,h3,h4,h5":
|
, "h1,h2,h3,h4,h5":
|
||||||
nest
|
nest
|
||||||
@ -76,7 +76,6 @@ mkGlobal maybeMode =
|
|||||||
$ css
|
$ css
|
||||||
{ boxSizing: str "inherit"
|
{ boxSizing: str "inherit"
|
||||||
}
|
}
|
||||||
, input
|
|
||||||
, form:
|
, form:
|
||||||
nested
|
nested
|
||||||
$ css
|
$ css
|
||||||
@ -155,7 +154,7 @@ defaultColours =
|
|||||||
-- highlight = Color.rgb 0x10 0x45 0x4A
|
-- highlight = Color.rgb 0x10 0x45 0x4A
|
||||||
darkBg = Color.rgb 0 0 0
|
darkBg = Color.rgb 0 0 0
|
||||||
|
|
||||||
lightBg = Color.rgb 255 255 255
|
lightBg = Color.rgb 250 250 250
|
||||||
|
|
||||||
type FlatTheme a =
|
type FlatTheme a =
|
||||||
{ background0 ∷ a
|
{ background0 ∷ a
|
||||||
@ -262,22 +261,8 @@ variables =
|
|||||||
fontVariables ∷ { main ∷ String, mono ∷ String } -> Style
|
fontVariables ∷ { main ∷ String, mono ∷ String } -> Style
|
||||||
fontVariables { main, mono } =
|
fontVariables { main, mono } =
|
||||||
css
|
css
|
||||||
{ "--mainFont": str $ main <> """, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol""""
|
{ "--main-font": str $ main <> """, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol""""
|
||||||
, "--monoFont": str $ mono <> ", monospace, monospace"
|
, "--mono-font": str $ mono <> ", monospace, monospace"
|
||||||
}
|
|
||||||
|
|
||||||
input ∷ StyleProperty
|
|
||||||
input =
|
|
||||||
nest
|
|
||||||
{ backgroundColor: "var(--input-bg-col)" # str
|
|
||||||
, padding: "5px" # str
|
|
||||||
, border: str "1px solid var(--bg-col)"
|
|
||||||
, borderRadius: "5px" # str
|
|
||||||
, fontSize: "12px" # str
|
|
||||||
, paddingBottom: "4px" # str
|
|
||||||
, paddingLeft: "8px" # str
|
|
||||||
, "&:disabled": nest { color: str "var(--input-text-col-disabled)" }
|
|
||||||
, "&:focus": nested inputFocus
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Standalone style for storybook
|
-- Standalone style for storybook
|
||||||
|
32
src/Yoga/Block/Icon/SVG/EyeClosed.purs
Normal file
32
src/Yoga/Block/Icon/SVG/EyeClosed.purs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
module Yoga.Block.Icon.SVG.EyeClosed where
|
||||||
|
|
||||||
|
import React.Basic (JSX)
|
||||||
|
import React.Basic.DOM as R
|
||||||
|
import React.Basic.DOM.SVG as SVG
|
||||||
|
|
||||||
|
eyeClosed ∷ JSX
|
||||||
|
eyeClosed =
|
||||||
|
SVG.svg
|
||||||
|
{ viewBox: "0 0 100 100"
|
||||||
|
, xmlns: "http://www.w3.org/2000/svg"
|
||||||
|
, fillRule: "evenodd"
|
||||||
|
, clipRule: "evenodd"
|
||||||
|
, strokeLinejoin: "round"
|
||||||
|
, strokeMiterlimit: "1.5"
|
||||||
|
, children:
|
||||||
|
[ SVG.path
|
||||||
|
{ fill: "none"
|
||||||
|
, d: "M0 0h100v100H0z"
|
||||||
|
}
|
||||||
|
, SVG.path
|
||||||
|
{ d: "M5.492 63.902c-1.539-2.426-2.587-11.465-1.593-13.076.352.369 4.353-.86 4.732-.54 24.519 20.777 51.057 22.859 83.889.676.892-.603 2.312-1.948 3.567-.637.892 2.137 2.479 6.187 2.439 10.011-.858 3.046-4.013 8.107-6.554 10.666.091-3.033-1.654-9.054-2.787-11.919-1.169 1.053-4.237 3.361-5.557 4.507 2.021 6.439 3.704 10.343 4.342 13.77-1.418 2.716-6.433 6.382-8.172 6.837-.695-3.519-3.589-12.626-4.791-16.545-1.721 1.014-7.746 2.85-7.739 2.967.294 5.01 1.269 11.753 3.159 17.431-2.331 1.521-7.403 2.045-10.644 2.233-1.477-3.05-1.902-13.039-2.221-17.74-1.768.532-6.838.5-8.865.679-.682 5.829-.99 11.62-.47 17.094-2.634-.024-8.846-1.614-10.179-2.127-.34-.886.675-13.622.808-16.23-1.442-.074-7.906-2.268-8.801-2.513-.501 3.058-1.153 12.152-.578 14.598-1.516-.601-8.651-6.109-9.148-6.3-.617-3.543-.097-9.17.23-12.361-.919-.313-5.78-3.571-6.551-4.211-.87 8.919-.1 11.254.106 11.869-1.502-1.338-7.45-7.873-8.622-9.139z"
|
||||||
|
, fill: "var(--stroke-colour)"
|
||||||
|
}
|
||||||
|
, SVG.path
|
||||||
|
{ d: "M50.026 26.996c23.346 0 42.3 24.595 42.3 24.595s-18.954 17.592-42.3 17.592c-23.347 0-42.301-17.592-42.301-17.592s18.954-24.595 42.301-24.595z"
|
||||||
|
, fill: "none"
|
||||||
|
, stroke: "var(--stroke-colour)"
|
||||||
|
, strokeWidth: "8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
44
src/Yoga/Block/Icon/SVG/EyeOpen.purs
Normal file
44
src/Yoga/Block/Icon/SVG/EyeOpen.purs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
module Yoga.Block.Icon.SVG.EyeOpen where
|
||||||
|
|
||||||
|
import React.Basic (JSX)
|
||||||
|
import React.Basic.DOM as R
|
||||||
|
import React.Basic.DOM.SVG as SVG
|
||||||
|
|
||||||
|
eyeOpen ∷ JSX
|
||||||
|
eyeOpen =
|
||||||
|
SVG.svg
|
||||||
|
{ viewBox: "0 0 100 100"
|
||||||
|
, xmlns: "http://www.w3.org/2000/svg"
|
||||||
|
, fillRule: "evenodd"
|
||||||
|
, clipRule: "evenodd"
|
||||||
|
, strokeLinejoin: "round"
|
||||||
|
, strokeMiterlimit: "1.5"
|
||||||
|
, children:
|
||||||
|
[ SVG.path
|
||||||
|
{ fill: "none"
|
||||||
|
, d: "M0 0h100v100H0z"
|
||||||
|
}
|
||||||
|
, SVG.path
|
||||||
|
{ d: "M50.173 21.996c23.346 0 42.3 27.978 42.3 27.978s-18.954 27.979-42.3 27.979c-23.346 0-42.301-27.979-42.301-27.979s18.955-27.978 42.301-27.978z"
|
||||||
|
, fill: "none"
|
||||||
|
, stroke: "var(--stroke-colour)"
|
||||||
|
, strokeWidth: "8"
|
||||||
|
}
|
||||||
|
, SVG.circle
|
||||||
|
{ cx: "49.963"
|
||||||
|
, cy: "50.087"
|
||||||
|
, r: "24.205"
|
||||||
|
, fill: "none"
|
||||||
|
, stroke: "var(--stroke-colour)"
|
||||||
|
, strokeWidth: "6"
|
||||||
|
}
|
||||||
|
, SVG.circle
|
||||||
|
{ cx: "49.963"
|
||||||
|
, cy: "50.087"
|
||||||
|
, r: "9.748"
|
||||||
|
, fill: "var(--stroke-colour)"
|
||||||
|
, stroke: "var(--stroke-colour)"
|
||||||
|
, strokeWidth: "8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
src/Yoga/Block/Icon/SVG/Icon.purs
Normal file
13
src/Yoga/Block/Icon/SVG/Icon.purs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module Yoga.Block.Icon.SVG
|
||||||
|
( module Yoga.Block.Icon.SVG.On
|
||||||
|
, module Yoga.Block.Icon.SVG.Off
|
||||||
|
, module Yoga.Block.Icon.SVG.MagnifyingGlass
|
||||||
|
, module Yoga.Block.Icon.SVG.EyeClosed
|
||||||
|
, module Yoga.Block.Icon.SVG.EyeOpen
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Yoga.Block.Icon.SVG.On (on)
|
||||||
|
import Yoga.Block.Icon.SVG.Off (off)
|
||||||
|
import Yoga.Block.Icon.SVG.MagnifyingGlass (magnifyingGlass)
|
||||||
|
import Yoga.Block.Icon.SVG.EyeClosed (eyeClosed)
|
||||||
|
import Yoga.Block.Icon.SVG.EyeOpen (eyeOpen)
|
36
src/Yoga/Block/Icon/SVG/MagnifyingGlass.purs
Normal file
36
src/Yoga/Block/Icon/SVG/MagnifyingGlass.purs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
module Yoga.Block.Icon.SVG.MagnifyingGlass where
|
||||||
|
|
||||||
|
import React.Basic (JSX)
|
||||||
|
import React.Basic.DOM as R
|
||||||
|
import React.Basic.DOM.SVG as SVG
|
||||||
|
|
||||||
|
magnifyingGlass ∷ JSX
|
||||||
|
magnifyingGlass =
|
||||||
|
SVG.svg
|
||||||
|
{ viewBox: "0 0 100 100"
|
||||||
|
, xmlns: "http://www.w3.org/2000/svg"
|
||||||
|
, fillRule: "evenodd"
|
||||||
|
, clipRule: "evenodd"
|
||||||
|
, strokeLinejoin: "round"
|
||||||
|
, strokeMiterlimit: "1.5"
|
||||||
|
, children:
|
||||||
|
[ SVG.path
|
||||||
|
{ fill: "none"
|
||||||
|
, d: "M0 0h100v100H0z"
|
||||||
|
}
|
||||||
|
, SVG.circle
|
||||||
|
{ cx: "42.994"
|
||||||
|
, cy: "42.837"
|
||||||
|
, r: "30.313"
|
||||||
|
, fill: "none"
|
||||||
|
, stroke: "var(--stroke-colour)"
|
||||||
|
, strokeWidth: "10"
|
||||||
|
}
|
||||||
|
, SVG.path
|
||||||
|
{ d: "M66.723 66.665l24.062 24.062"
|
||||||
|
, fill: "none"
|
||||||
|
, stroke: "var(--stroke-colour)"
|
||||||
|
, strokeWidth: "8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
30
src/Yoga/Block/Icon/SVG/Off.purs
Normal file
30
src/Yoga/Block/Icon/SVG/Off.purs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
module Yoga.Block.Icon.SVG.Off where
|
||||||
|
|
||||||
|
import React.Basic (JSX)
|
||||||
|
import React.Basic.DOM as R
|
||||||
|
import React.Basic.DOM.SVG as SVG
|
||||||
|
|
||||||
|
off ∷ JSX
|
||||||
|
off =
|
||||||
|
SVG.svg
|
||||||
|
{ viewBox: "0 0 100 100"
|
||||||
|
, xmlns: "http://www.w3.org/2000/svg"
|
||||||
|
, fillRule: "evenodd"
|
||||||
|
, clipRule: "evenodd"
|
||||||
|
, strokeLinejoin: "round"
|
||||||
|
, strokeMiterlimit: "1.5"
|
||||||
|
, children:
|
||||||
|
[ SVG.path
|
||||||
|
{ fill: "none"
|
||||||
|
, d: "M0 0h100v100H0z"
|
||||||
|
}
|
||||||
|
, SVG.circle
|
||||||
|
{ cx: "50"
|
||||||
|
, cy: "50"
|
||||||
|
, r: "37.808"
|
||||||
|
, fill: "none"
|
||||||
|
, stroke: "var(--stroke-colour)"
|
||||||
|
, strokeWidth: "20"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
41
src/Yoga/Block/Icon/SVG/On.purs
Normal file
41
src/Yoga/Block/Icon/SVG/On.purs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
module Yoga.Block.Icon.SVG.On where
|
||||||
|
|
||||||
|
import React.Basic (JSX)
|
||||||
|
-- import React.Basic.DOM as R
|
||||||
|
import React.Basic.DOM.SVG as SVG
|
||||||
|
|
||||||
|
on ∷ JSX
|
||||||
|
on =
|
||||||
|
SVG.svg
|
||||||
|
{ viewBox: "0 0 100 100"
|
||||||
|
, xmlns: "http://www.w3.org/2000/svg"
|
||||||
|
, fillRule: "evenodd"
|
||||||
|
, clipRule: "evenodd"
|
||||||
|
, strokeLinejoin: "round"
|
||||||
|
, strokeMiterlimit: "1.5"
|
||||||
|
, children:
|
||||||
|
[ SVG.path
|
||||||
|
{ fill: "none"
|
||||||
|
, d: "M0 0h100v100H0z"
|
||||||
|
}
|
||||||
|
, SVG.clipPath
|
||||||
|
{ id: "a"
|
||||||
|
, children:
|
||||||
|
[ SVG.path
|
||||||
|
{ d: "M0 0h100v100H0z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
, SVG.g
|
||||||
|
{ clipPath: "url(#a)"
|
||||||
|
, children:
|
||||||
|
[ SVG.path
|
||||||
|
{ d: "M50 1.921v96.261"
|
||||||
|
, fill: "none"
|
||||||
|
, stroke: "var(--stroke-colour)"
|
||||||
|
, strokeWidth: "20"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
25
src/Yoga/Block/Icon/SVG/QuestionMark.purs
Normal file
25
src/Yoga/Block/Icon/SVG/QuestionMark.purs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module Yoga.Block.Icon.SVG.QuestionMark where
|
||||||
|
|
||||||
|
import React.Basic (JSX)
|
||||||
|
import React.Basic.DOM as R
|
||||||
|
import React.Basic.DOM.SVG as SVG
|
||||||
|
|
||||||
|
questionMark :: JSX
|
||||||
|
questionMark = SVG.svg
|
||||||
|
{ viewBox: "0 0 100 100"
|
||||||
|
, xmlns: "http://www.w3.org/2000/svg"
|
||||||
|
, fillRule: "evenodd"
|
||||||
|
, clipRule: "evenodd"
|
||||||
|
, strokeLinejoin: "round"
|
||||||
|
, strokeMiterlimit: "2"
|
||||||
|
, children:
|
||||||
|
[ SVG.path
|
||||||
|
{ fill: "none"
|
||||||
|
, d: "M0 0h100v100H0z"
|
||||||
|
}
|
||||||
|
, SVG.path
|
||||||
|
{ d: "M50 10.037c22.056 0 39.963 17.907 39.963 39.963S72.056 89.963 50 89.963 10.037 72.056 10.037 50 27.944 10.037 50 10.037zM48.871 77.03c2.87 0 5.326-2.384 5.351-5.351-.025-2.918-2.481-5.301-5.351-5.301-2.967 0-5.374 2.383-5.35 5.301-.024 2.967 2.383 5.351 5.35 5.351zm-4.255-15.176h8.098v-.632c.049-5.156 1.727-7.515 5.691-9.947 4.474-2.675 7.271-6.323 7.271-11.892 0-8.22-6.396-13.375-15.686-13.375-8.512 0-15.418 4.718-15.661 13.959h8.657c.219-4.572 3.526-6.761 6.955-6.761 3.721 0 6.713 2.481 6.713 6.299 0 3.405-2.262 5.739-5.205 7.587-4.304 2.676-6.785 5.375-6.833 14.13v.632z"
|
||||||
|
, fill: "#333"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
1
src/Yoga/Block/Icon/SVG/eyeClosed.svg
Normal file
1
src/Yoga/Block/Icon/SVG/eyeClosed.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.5"><path fill="none" d="M0 0h100v100H0z"/><path d="M5.492 63.902c-1.539-2.426-2.587-11.465-1.593-13.076.352.369 4.353-.86 4.732-.54 24.519 20.777 51.057 22.859 83.889.676.892-.603 2.312-1.948 3.567-.637.892 2.137 2.479 6.187 2.439 10.011-.858 3.046-4.013 8.107-6.554 10.666.091-3.033-1.654-9.054-2.787-11.919-1.169 1.053-4.237 3.361-5.557 4.507 2.021 6.439 3.704 10.343 4.342 13.77-1.418 2.716-6.433 6.382-8.172 6.837-.695-3.519-3.589-12.626-4.791-16.545-1.721 1.014-7.746 2.85-7.739 2.967.294 5.01 1.269 11.753 3.159 17.431-2.331 1.521-7.403 2.045-10.644 2.233-1.477-3.05-1.902-13.039-2.221-17.74-1.768.532-6.838.5-8.865.679-.682 5.829-.99 11.62-.47 17.094-2.634-.024-8.846-1.614-10.179-2.127-.34-.886.675-13.622.808-16.23-1.442-.074-7.906-2.268-8.801-2.513-.501 3.058-1.153 12.152-.578 14.598-1.516-.601-8.651-6.109-9.148-6.3-.617-3.543-.097-9.17.23-12.361-.919-.313-5.78-3.571-6.551-4.211-.87 8.919-.1 11.254.106 11.869-1.502-1.338-7.45-7.873-8.622-9.139z" fill="#333"/><path d="M50.026 26.996c23.346 0 42.3 24.595 42.3 24.595s-18.954 17.592-42.3 17.592c-23.347 0-42.301-17.592-42.301-17.592s18.954-24.595 42.301-24.595z" fill="none" stroke="#333" stroke-width="8"/></svg>
|
After Width: | Height: | Size: 1.3 KiB |
1
src/Yoga/Block/Icon/SVG/eyeOpen.svg
Normal file
1
src/Yoga/Block/Icon/SVG/eyeOpen.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.5"><path fill="none" d="M0 0h100v100H0z"/><path d="M50.173 21.996c23.346 0 42.3 27.978 42.3 27.978s-18.954 27.979-42.3 27.979c-23.346 0-42.301-27.979-42.301-27.979s18.955-27.978 42.301-27.978z" fill="none" stroke="#333" stroke-width="8"/><circle cx="49.963" cy="50.087" r="24.205" fill="none" stroke="#333" stroke-width="6"/><circle cx="49.963" cy="50.087" r="9.748" fill="#333" stroke="#333" stroke-width="8"/></svg>
|
After Width: | Height: | Size: 564 B |
1
src/Yoga/Block/Icon/SVG/magnifyingGlass.svg
Normal file
1
src/Yoga/Block/Icon/SVG/magnifyingGlass.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.5"><path fill="none" d="M0 0h100v100H0z"/><circle cx="42.994" cy="42.837" r="30.313" fill="none" stroke="#333" stroke-width="10"/><path d="M66.723 66.665l24.062 24.062" fill="none" stroke="#333" stroke-width="8"/></svg>
|
After Width: | Height: | Size: 366 B |
1
src/Yoga/Block/Icon/SVG/off.svg
Normal file
1
src/Yoga/Block/Icon/SVG/off.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.5"><path fill="none" d="M0 0h100v100H0z"/><circle cx="50" cy="50" r="37.808" fill="none" stroke="#333" stroke-width="20"/></svg>
|
After Width: | Height: | Size: 275 B |
1
src/Yoga/Block/Icon/SVG/on.svg
Normal file
1
src/Yoga/Block/Icon/SVG/on.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.5"><path fill="none" d="M0 0h100v100H0z"/><clipPath id="a"><path d="M0 0h100v100H0z"/></clipPath><g clip-path="url(#a)"><path d="M50 1.921v96.261" fill="none" stroke="#333" stroke-width="20"/></g></svg>
|
After Width: | Height: | Size: 349 B |
1
src/Yoga/Block/Icon/SVG/questionMark.svg
Normal file
1
src/Yoga/Block/Icon/SVG/questionMark.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2"><path fill="none" d="M0 0h100v100H0z"/><path d="M50 10.037c22.056 0 39.963 17.907 39.963 39.963S72.056 89.963 50 89.963 10.037 72.056 10.037 50 27.944 10.037 50 10.037zM48.871 77.03c2.87 0 5.326-2.384 5.351-5.351-.025-2.918-2.481-5.301-5.351-5.301-2.967 0-5.374 2.383-5.35 5.301-.024 2.967 2.383 5.351 5.35 5.351zm-4.255-15.176h8.098v-.632c.049-5.156 1.727-7.515 5.691-9.947 4.474-2.675 7.271-6.323 7.271-11.892 0-8.22-6.396-13.375-15.686-13.375-8.512 0-15.418 4.718-15.661 13.959h8.657c.219-4.572 3.526-6.761 6.955-6.761 3.721 0 6.713 2.481 6.713 6.299 0 3.405-2.262 5.739-5.205 7.587-4.304 2.676-6.785 5.375-6.833 14.13v.632z" fill="#333"/></svg>
|
After Width: | Height: | Size: 796 B |
@ -11,6 +11,7 @@ module Yoga.Prelude.Default
|
|||||||
, module Data.Foldable
|
, module Data.Foldable
|
||||||
, module Data.FoldableWithIndex
|
, module Data.FoldableWithIndex
|
||||||
, module Data.FunctorWithIndex
|
, module Data.FunctorWithIndex
|
||||||
|
, runMaybeT_
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
@ -25,3 +26,6 @@ import Data.Maybe (Maybe(..), fromMaybe, fromMaybe', isJust, maybe)
|
|||||||
import Data.Monoid (guard)
|
import Data.Monoid (guard)
|
||||||
import Effect (Effect)
|
import Effect (Effect)
|
||||||
import Effect.Class (liftEffect)
|
import Effect.Class (liftEffect)
|
||||||
|
|
||||||
|
runMaybeT_ ∷ ∀ f a. Functor f => MaybeT f a -> f Unit
|
||||||
|
runMaybeT_ = void <<< runMaybeT
|
||||||
|
46
yarn.lock
46
yarn.lock
@ -4854,25 +4854,23 @@ fragment-cache@^0.2.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
map-cache "^0.2.2"
|
map-cache "^0.2.2"
|
||||||
|
|
||||||
framer-motion@^2.7.0:
|
framer-motion@^3.0.0:
|
||||||
version "2.9.5"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-2.9.5.tgz#bbb185325d531c57f494cf3f6cf7719fc2c225c7"
|
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-3.1.1.tgz#a8a779501213b7ce02cc35beb27621d73cc2f1e7"
|
||||||
integrity sha512-epSX4Co1YbDv0mjfHouuY0q361TpHE7WQzCp/xMTilxy4kXd+Z23uJzPVorfzbm1a/9q1Yu8T5bndaw65NI4Tg==
|
integrity sha512-Gm1QSb0xUxuhcPar5FIs5Ws+STrhLZ6XZf2Io8dVwFofe1OzwkL9asGFVu7z3y6WqC4Hvnxm7wsW5SBHlxZDYw==
|
||||||
dependencies:
|
dependencies:
|
||||||
framesync "^4.1.0"
|
framesync "^5.0.0"
|
||||||
hey-listen "^1.0.8"
|
hey-listen "^1.0.8"
|
||||||
popmotion "9.0.0-rc.20"
|
popmotion "^9.0.2"
|
||||||
style-value-types "^3.1.9"
|
style-value-types "^3.2.0"
|
||||||
tslib "^1.10.0"
|
tslib "^1.10.0"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@emotion/is-prop-valid" "^0.8.2"
|
"@emotion/is-prop-valid" "^0.8.2"
|
||||||
|
|
||||||
framesync@^4.1.0:
|
framesync@5.0.0, framesync@^5.0.0:
|
||||||
version "4.1.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/framesync/-/framesync-4.1.0.tgz#69a8db3ca432dc70d6a76ba882684a1497ef068a"
|
resolved "https://registry.yarnpkg.com/framesync/-/framesync-5.0.0.tgz#7de8caedf53ac441118e79680f1beb7391c328b6"
|
||||||
integrity sha512-MmgZ4wCoeVxNbx2xp5hN/zPDCbLSKiDt4BbbslK7j/pM2lg5S0vhTNv1v8BCVb99JPIo6hXBFdwzU7Q4qcAaoQ==
|
integrity sha512-wd8t+JsQGisluSv1twiEeDv0aNGpavGb9q7xgIk9fGbcIWkNXF/KVtrjnOrCwBWJuiXxlJfNkcvGudsI32FxYA==
|
||||||
dependencies:
|
|
||||||
hey-listen "^1.0.5"
|
|
||||||
|
|
||||||
fresh@0.5.2:
|
fresh@0.5.2:
|
||||||
version "0.5.2"
|
version "0.5.2"
|
||||||
@ -5315,7 +5313,7 @@ he@^1.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||||
|
|
||||||
hey-listen@^1.0.5, hey-listen@^1.0.8:
|
hey-listen@^1.0.8:
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68"
|
resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68"
|
||||||
integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==
|
integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==
|
||||||
@ -7489,14 +7487,14 @@ polished@^3.4.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.9.2"
|
"@babel/runtime" "^7.9.2"
|
||||||
|
|
||||||
popmotion@9.0.0-rc.20:
|
popmotion@^9.0.2:
|
||||||
version "9.0.0-rc.20"
|
version "9.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-9.0.0-rc.20.tgz#f3550042ae31957b5416793ae8723200951ad39d"
|
resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-9.0.2.tgz#477650c3b4af97161011809223d9ca6860f3a2b5"
|
||||||
integrity sha512-f98sny03WuA+c8ckBjNNXotJD4G2utG/I3Q23NU69OEafrXtxxSukAaJBxzbtxwDvz3vtZK69pu9ojdkMoBNTg==
|
integrity sha512-WfSg8IfoUwYIP9uqeqbgncIsMHLAKWqebT2IP1aGAI6gdSJqTPy/H8NvP4ZyDtDCUCx5Yh3Pth/7iUJjIwR7LA==
|
||||||
dependencies:
|
dependencies:
|
||||||
framesync "^4.1.0"
|
framesync "5.0.0"
|
||||||
hey-listen "^1.0.8"
|
hey-listen "^1.0.8"
|
||||||
style-value-types "^3.1.9"
|
style-value-types "3.2.0"
|
||||||
tslib "^1.10.0"
|
tslib "^1.10.0"
|
||||||
|
|
||||||
portfinder@^1.0.26:
|
portfinder@^1.0.26:
|
||||||
@ -9087,10 +9085,10 @@ style-loader@^1.2.1:
|
|||||||
loader-utils "^2.0.0"
|
loader-utils "^2.0.0"
|
||||||
schema-utils "^2.7.0"
|
schema-utils "^2.7.0"
|
||||||
|
|
||||||
style-value-types@^3.1.9:
|
style-value-types@3.2.0, style-value-types@^3.2.0:
|
||||||
version "3.1.9"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-3.1.9.tgz#faf7da660d3f284ed695cff61ea197d85b9122cc"
|
resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-3.2.0.tgz#eb89cab1340823fa7876f3e289d29d99c92111bb"
|
||||||
integrity sha512-050uqgB7WdvtgacoQKm+4EgKzJExVq0sieKBQQtJiU3Muh6MYcCp4T3M8+dfl6VOF2LR0NNwXBP1QYEed8DfIw==
|
integrity sha512-ih0mGsrYYmVvdDi++/66O6BaQPRPRMQHoZevNNdMMcPlP/cH28Rnfsqf1UEba/Bwfuw9T8BmIMwbGdzsPwQKrQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
hey-listen "^1.0.8"
|
hey-listen "^1.0.8"
|
||||||
tslib "^1.10.0"
|
tslib "^1.10.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user