Refactor Hooks

This commit is contained in:
Mark Eibes 2020-12-25 15:54:45 +01:00
parent 55a6f6fc66
commit a0f3e37442
9 changed files with 96 additions and 62 deletions

View File

@ -103,6 +103,7 @@ popover = do
, stiffness: 200.0
, damping: 20.0
, mass: 0.7
, delay: 0.3
}
}
{ placement: Placement Placement.Bottom (Just Placement.Start)

View File

@ -10,13 +10,13 @@ import Data.TwoOrMore as TwoOrMore
import Effect.Aff (delay)
import Effect.Unsafe (unsafePerformEffect)
import Foreign.Object as Object
import Hooks.Key as Key
import Hooks.UseResize (useResize)
import Yoga.Block.Hook.Key as Key
import Yoga.Block.Hook.UseResize (useResize)
import Yoga.Block.Hook.UseKeyDown (useKeyDown)
import Math as Math
import React.Basic.DOM (css)
import React.Basic.DOM as R
import React.Basic.Emotion as E
import React.Basic.Extra.Hooks.UseKeyDown (useKeyDown)
import React.Basic.Hooks (reactComponent)
import React.Basic.Hooks as React
import React.Basic.Hooks.Aff (useAff)

View File

@ -9,7 +9,7 @@ import Effect.Unsafe (unsafePerformEffect)
import Foreign.Object as Object
import Framer.Motion (VariantLabel)
import Framer.Motion as Motion
import Hooks.Scroll (useScrollPosition)
import Yoga.Block.Hook.Scroll (useScrollPosition)
import Literals.Undefined (undefined)
import MotionValue (useMotionValue)
import MotionValue as MotionValue
@ -21,12 +21,12 @@ import React.Basic.Hooks as React
import Unsafe.Coerce (unsafeCoerce)
import Yoga.Block.Atom.Segmented.Style as Style
type Props =
{ activeItemRefs ∷ TwoOrMore (Ref (Nullable Node))
, activeItemIndex ∷ Int
, updateActiveIndex ∷ Int -> Effect Unit
, windowWidth ∷ Number
}
type Props
= { activeItemRefs ∷ TwoOrMore (Ref (Nullable Node))
, activeItemIndex ∷ Int
, updateActiveIndex ∷ Int -> Effect Unit
, windowWidth ∷ Number
}
component ∷ ReactComponent Props
component =
@ -42,14 +42,16 @@ component =
_ <-
runMaybeT do
rawStyles <- traverse getStyle props.activeItemRefs
let styles = rawStyles <#> \s -> s { left = s.left + scrollX }
let
styles = rawStyles <#> \s -> s { left = s.left + scrollX }
unless (maybeAnimationVariants == Just styles) do
setVariants (Just styles) # lift
mempty
useLayoutEffect maybeDragX do
case maybeDragX, maybeAnimationVariants of
Just x, Just animationVariants -> do
let { left, width } = handleDrag { activeItemIndex: props.activeItemIndex, animationVariants, x }
let
{ left, width } = handleDrag { activeItemIndex: props.activeItemIndex, animationVariants, x }
activeLeft # MotionValue.set left
activeWidth # MotionValue.set width
_, _ -> mempty
@ -88,9 +90,12 @@ component =
when (isJust maybeDragX) $ setDragX (Just pi.point.x)
, onDragEnd:
Motion.onDragEnd \_ pi -> do
let x = maybeDragX # fromMaybe' \_ -> unsafeCrashWith "no x should not happen"
let newIdx = findOverlapping props.activeItemIndex animationVariants x
let v = animationVariants TwoOrMore.!! newIdx # fromMaybe' \_ -> unsafeCrashWith "omg"
let
x = maybeDragX # fromMaybe' \_ -> unsafeCrashWith "no x should not happen"
let
newIdx = findOverlapping props.activeItemIndex animationVariants x
let
v = animationVariants TwoOrMore.!! newIdx # fromMaybe' \_ -> unsafeCrashWith "omg"
setDragX Nothing
activeLeft # MotionValue.set v.left
activeWidth # MotionValue.set v.width
@ -118,18 +123,23 @@ getStyle itemRef = do
indexToVariant ∷ Int -> VariantLabel
indexToVariant = show >>> unsafeCoerce
type BBox =
{ top ∷ Number, left ∷ Number, width ∷ Number, height ∷ Number }
type BBox
= { top ∷ Number, left ∷ Number, width ∷ Number, height ∷ Number }
findOverlapping ∷ Int -> TwoOrMore BBox -> Number -> Int
findOverlapping activeIndex styles x =
fromMaybe activeIndex do
curr <- styles TwoOrMore.!! activeIndex
let fst = TwoOrMore.head styles
let lst = TwoOrMore.last styles
let inside e = (e.left < x) && (e.left + e.width) >= x
let tooFarLeft = MZ.guard (x <= fst.left + fst.width) $> 0
let tooFarRight = MZ.guard (x >= lst.left) $> TwoOrMore.length styles - 1
let
fst = TwoOrMore.head styles
let
lst = TwoOrMore.last styles
let
inside e = (e.left < x) && (e.left + e.width) >= x
let
tooFarLeft = MZ.guard (x <= fst.left + fst.width) $> 0
let
tooFarRight = MZ.guard (x >= lst.left) $> TwoOrMore.length styles - 1
TwoOrMore.findIndex inside styles <|> tooFarLeft <|> tooFarRight
handleDrag ∷
@ -139,11 +149,16 @@ handleDrag ∷
} ->
{ left ∷ Number, width ∷ Number }
handleDrag { x, activeItemIndex, animationVariants } = do
let idx = findOverlapping activeItemIndex animationVariants x
let av = animationVariants
let firstVariant = av # TwoOrMore.head
let lastVariant = av # TwoOrMore.last
let baseVariant = av TwoOrMore.!! idx # fromMaybe' \_ -> unsafeCrashWith "shit"
let
idx = findOverlapping activeItemIndex animationVariants x
let
av = animationVariants
let
firstVariant = av # TwoOrMore.head
let
lastVariant = av # TwoOrMore.last
let
baseVariant = av TwoOrMore.!! idx # fromMaybe' \_ -> unsafeCrashWith "shit"
let
closestVariant =
if x >= (baseVariant.left + (baseVariant.width / 2.0)) then
@ -157,25 +172,41 @@ handleDrag { x, activeItemIndex, animationVariants } = do
else
closestVariant /\ baseVariant
-- Total
let rangeStart = smaller.left + (smaller.width / 2.0)
let rangeEnd = greater.left + (greater.width / 2.0)
let range = rangeEnd - rangeStart
let ratio = ((x - rangeStart) / range)
let interpolatedWidth = (greater.width * ratio) + smaller.width * (1.0 - ratio)
let
rangeStart = smaller.left + (smaller.width / 2.0)
let
rangeEnd = greater.left + (greater.width / 2.0)
let
range = rangeEnd - rangeStart
let
ratio = ((x - rangeStart) / range)
let
interpolatedWidth = (greater.width * ratio) + smaller.width * (1.0 - ratio)
-- Right
let rangeStartRight = smaller.left + smaller.width
let rangeEndRight = greater.left + greater.width
let rangeRight = rangeEndRight - rangeStartRight
let ratioRight = ((x + (interpolatedWidth / 2.0) - rangeStartRight) / rangeRight)
let
rangeStartRight = smaller.left + smaller.width
let
rangeEndRight = greater.left + greater.width
let
rangeRight = rangeEndRight - rangeStartRight
let
ratioRight = ((x + (interpolatedWidth / 2.0) - rangeStartRight) / rangeRight)
-- Left
let rangeStartLeft = smaller.left
let rangeEndLeft = greater.left
let rangeLeft = rangeEndLeft - rangeStartLeft
let ratioLeft = (((x - (interpolatedWidth / 2.0)) - rangeStartLeft) / rangeLeft)
let
rangeStartLeft = smaller.left
let
rangeEndLeft = greater.left
let
rangeLeft = rangeEndLeft - rangeStartLeft
let
ratioLeft = (((x - (interpolatedWidth / 2.0)) - rangeStartLeft) / rangeLeft)
-- Individual
let left = rangeStartLeft + (ratioLeft * rangeLeft)
let right = rangeStartRight + (ratioRight * rangeRight)
let width = right - left
let
left = rangeStartLeft + (ratioLeft * rangeLeft)
let
right = rangeStartRight + (ratioRight * rangeRight)
let
width = right - left
if x < firstVariant.left then
{ left: firstVariant.left, width: firstVariant.width }
else

View File

@ -1,4 +1,4 @@
module Hooks.Key where
module Yoga.Block.Hook.Key where
import Data.Maybe (Maybe(..))
import Web.Event.Event (Event)

View File

@ -1,4 +1,4 @@
module Hooks.Scroll where
module Yoga.Block.Hook.Scroll where
import Prelude
import Data.Newtype (class Newtype)
@ -20,12 +20,12 @@ registerListener listener = do
addEventListener eventType listener false target
pure $ removeEventListener eventType listener false target
newtype UseScrollPosition hooks = UseScrollPosition (UseLayoutEffect Unit (UseState ScrollPosition hooks))
newtype UseScrollPosition hooks
= UseScrollPosition (UseLayoutEffect Unit (UseState ScrollPosition hooks))
derive instance ntUseScrollPosition ∷ Newtype (UseScrollPosition hooks) _
type ScrollPosition =
{ scrollX ∷ Number, scrollY ∷ Number }
type ScrollPosition
= { scrollX ∷ Number, scrollY ∷ Number }
useScrollPosition ∷ Hook UseScrollPosition ScrollPosition
useScrollPosition =

View File

@ -1,19 +1,19 @@
module React.Basic.Extra.Hooks.UseKeyDown where
module Yoga.Block.Hook.UseKeyDown where
import Prelude
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Effect (Effect)
import Hooks.Key (KeyCode, getKeyCode, intToKeyCode)
import Yoga.Block.Hook.Key (KeyCode, getKeyCode, intToKeyCode)
import React.Basic.Hooks (Hook, UseEffect, coerceHook, useEffectAlways)
import Web.Event.Event (EventType(..))
import Web.Event.EventTarget (addEventListener, eventListener, removeEventListener)
import Web.HTML (window)
import Web.HTML.Window as Win
newtype UseKeyDown hooks = UseKeyDown
newtype UseKeyDown hooks
= UseKeyDown
(UseEffect Unit hooks)
derive instance ntUseKeyDown ∷ Newtype (UseKeyDown hooks) _
useKeyDown ∷ (KeyCode -> Effect Unit) -> Hook UseKeyDown Unit

View File

@ -1,19 +1,19 @@
module React.Basic.Extra.Hooks.UseKeyUp where
module Yoga.Block.Hook.UseKeyUp where
import Prelude
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Effect (Effect)
import Hooks.Key (KeyCode, getKeyCode, intToKeyCode)
import Yoga.Block.Hook.Key (KeyCode, getKeyCode, intToKeyCode)
import React.Basic.Hooks (Hook, UseEffect, coerceHook, useEffect)
import Web.Event.Event (EventType(..))
import Web.Event.EventTarget (addEventListener, eventListener, removeEventListener)
import Web.HTML (window)
import Web.HTML.Window as Win
newtype UseKeyUp hooks = UseKeyUp
newtype UseKeyUp hooks
= UseKeyUp
(UseEffect Unit hooks)
derive instance ntUseKeyUp ∷ Newtype (UseKeyUp hooks) _
useKeyUp ∷ (KeyCode -> Effect Unit) -> Hook UseKeyUp Unit

View File

@ -1,4 +1,4 @@
module Hooks.UseResize where
module Yoga.Block.Hook.UseResize where
import Prelude
import Data.Int (toNumber)
@ -20,15 +20,16 @@ registerListener listener = do
addEventListener eventType listener false target
pure $ removeEventListener eventType listener false target
newtype UseResize hooks = UseResize (UseLayoutEffect Unit (UseState { width ∷ Number, height ∷ Number } hooks))
newtype UseResize hooks
= UseResize (UseLayoutEffect Unit (UseState { width ∷ Number, height ∷ Number } hooks))
derive instance ntUseResize ∷ Newtype (UseResize hooks) _
useResize ∷ Hook UseResize { width ∷ Number, height ∷ Number }
useResize =
coerceHook React.do
size /\ updateSize <- useState { width: 0.0, height: 0.0 }
let setSize = updateSize <<< const
let
setSize = updateSize <<< const
useLayoutEffect unit do
setSizeFromWindow setSize
listener <- makeListener setSize
@ -51,7 +52,8 @@ useResize' ∷ Effect Unit -> Hook UseResize { width ∷ Number, height ∷ Numb
useResize' eff =
coerceHook React.do
size /\ updateSize <- useState { width: 0.0, height: 0.0 }
let setSize = updateSize <<< const
let
setSize = updateSize <<< const
useLayoutEffect unit do
setSizeFromWindow setSize
listener <- makeListener (setSize >=> const eff)