@@ -1,13 +1,18 @@
11module Yoga.Block.Atom.Input.View where
22
33import Yoga.Prelude.View
4+import Data.Array as Array
5+import Data.Interpolate (i)
6+import Data.Semigroup.Foldable (intercalateMap)
47import Data.String.NonEmpty (NonEmptyString)
58import Data.String.NonEmpty as NonEmptyString
69import Data.Symbol (SProxy(..))
10+import Debug.Trace (spy)
711import Foreign.Object (Object)
812import Foreign.Object as Object
913import Framer.Motion as M
10−import React.Basic.DOM (css)
14+import Partial.Unsafe (unsafeCrashWith)
15+import React.Basic.DOM (CSS, css)
1116import React.Basic.DOM as R
1217import React.Basic.Hooks as React
1318import Web.HTML.HTMLInputElement as InputElement
@@ -18,19 +23,19 @@ import Yoga.Block.Atom.Input.Types as HTMLInput
1823import Yoga.Block.Icon.SVG as SVGIcon
1924import Yoga.Block.Internal.OptionalProp (asMaybe)
2025
21−type PropsF f
22− = ( leading ∷ f JSX
23− , trailing ∷ f JSX
24− , label ∷ f NonEmptyString
25− , type ∷ f HTMLInput
26− | Style.Props f InputProps
27− )
26+type PropsF f =
27+ ( leading ∷ f JSX
28+ , trailing ∷ f JSX
29+ , label ∷ f NonEmptyString
30+ , type ∷ f HTMLInput
31+ | Style.Props f InputProps
32+ )
2833
29−type Props
30− = PropsF Id
34+type Props =
35+ PropsF Id
3136
32−type PropsOptional
33− = PropsF OptionalProp
37+type PropsOptional =
38+ PropsF OptionalProp
3439
3540component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
3641component = rawComponent
@@ -47,6 +52,68 @@ mkLeftIcon icon =
4752 }
4853 ]
4954
55+containerVariants ∷
56+ { blurred ∷ CSS
57+ , focussed ∷ CSS
58+ }
59+containerVariants =
60+ { focussed:
61+ css
62+ { clipPath
63+ , transition: { duration: 1.3 }
64+ }
65+ , blurred:
66+ css
67+ { clipPath:
68+ drawPathUntil (Array.length path) path
69+ }
70+ }
71+ where
72+ clipPath = 3 Array... (Array.length path / 2 + 1) <#> \ln -> drawPathUntil (ln * 2) path
73+
74+type Point =
75+ { x ∷ Int, y ∷ Int }
76+
77+p ∷ Int -> Int -> Point
78+p x y = { x, y }
79+
80+drawPathUntil ∷ Int -> Array Point -> String
81+drawPathUntil idx thePath = do
82+ let fn { x, y } = i x "%" " " y "%"
83+ let firstFew = Array.take idx thePath
84+ let lastFew = Array.drop idx thePath $> (Array.last firstFew # fromMaybe' \_ -> unsafeCrashWith "ogod")
85+ let rendered = intercalate "," $ fn <$> (firstFew <> lastFew)
86+ spy "polybius" $ i "polygon(" rendered ")"
87+
88+path ∷ Array Point
89+path = mkPath 5
90+
91+mkPath ∷ Int -> Array Point
92+mkPath d = do
93+ let
94+ inside =
95+ [ p d d
96+ , p (100 - d) d
97+ , p (100 - d) (100 - d)
98+ , p d (100 - d)
99+ , p d d
100+ ]
101+ outside =
102+ [ p d 0
103+ , p 100 0
104+ , p 100 100
105+ , p 0 100
106+ , p 0 0
107+ , p d 0 -- one turn, starting way back
108+ ]
109+ inside <> outside <> (Array.reverse inside)
110+
111+containerVariantLabels ∷
112+ { blurred ∷ M.VariantLabel
113+ , focussed ∷ M.VariantLabel
114+ }
115+containerVariantLabels = M.makeVariantLabels containerVariants
116+
50117rawComponent ∷ ∀ p. ReactComponent { | p }
51118rawComponent =
52119 mkForwardRefComponent "Input" do
@@ -54,8 +121,7 @@ rawComponent =
54121 inputBbox /\ setInputBbox <- useState' (zero ∷ DOMRect)
55122 hasFocus /\ setHasFocus <- useState' false
56123 backupRef ∷ NodeRef <- useRef null -- [TODO] test this
57− let
58− ref = forwardedRefAsMaybe propsRef # fromMaybe backupRef
124+ let ref = forwardedRefAsMaybe propsRef # fromMaybe backupRef
59125 useEffectOnce do
60126 maybeBBox <- getBoundingBoxFromRef ref
61127 for_ maybeBBox setInputBbox
@@ -73,8 +139,7 @@ rawComponent =
73139 maybeBBox <- getBoundingBoxFromRef leftIconRef
74140 for_ maybeBBox (setLeftIconBbox <<< Just)
75141 mempty
76− let
77− (maybeValue ∷ Maybe String) = cast props.value # opToMaybe
142+ let (maybeValue ∷ Maybe String) = cast props.value # opToMaybe
78143 hasValue /\ setHasValue <- useState' ((maybeValue # isJust) && (maybeValue /= Just ""))
79144 let
80145 aria ∷ Object String
@@ -138,22 +203,25 @@ rawComponent =
138203 ( const do
139204 when hasFocus $ setHasFocus false
140205 el <- getHTMLElementFromRef ref
141− let
142− inputEl = InputElement.fromHTMLElement =<< el
206+ let inputEl = InputElement.fromHTMLElement =<< el
143207 for_ inputEl \ie -> do
144208 v <- InputElement.value ie
145209 setHasValue (v /= "")
146210 )
147211 onFocus = handler preventDefault (const $ unless hasFocus $ setHasFocus true)
148212 inputWrapper =
149− div
150− </* { className: "ry-input-wrapper"
151− , css: Style.inputWrapper props
152− , _data:
153− Object.fromHomogeneous
154− { "invalid": aria # Object.lookup "invalid" # fromMaybe ""
155− }
156− }
213+ M.div
214+ </* M.motion
215+ { variants: M.variants containerVariants
216+ , animate: M.animate if hasFocus then containerVariantLabels.focussed else containerVariantLabels.blurred
217+ }
218+ { className: "ry-input-wrapper"
219+ , css: Style.inputWrapper props
220+ , _data:
221+ Object.fromHomogeneous
222+ { "invalid": aria # Object.lookup "invalid" # fromMaybe ""
223+ }
224+ }
157225 /> [ leading # foldMap \l -> div </ { ref: leftIconRef } /> [ l ]
158226 , emotionInput
159227 ref
@@ -230,10 +298,8 @@ password =
230298 ]
231299 ]
232300 ]
233− let
234− trailing = props.trailing ?|| eyeCon
235− let
236− leading = props.leading ?|| mempty
301+ let trailing = props.trailing ?|| eyeCon
302+ let leading = props.leading ?|| mempty
237303 pure
238304 $ div
239305 </* { className: "ry-input-wrapper"