git.iko.soy/rowtype-yoga/psfp
on master help sign in
Add react-spring
commit65bcaa6f58ad053ace70127b31265cc663962ecc authorMark Eibes <mark.eibes@gmail.com> dateWed 1 Apr 2020, 23:37 (7 years ago) parent88d4be0
17 files changed+187−60
components/package-lock.json+9 components/package.json+2−1 components/src/React/Basic/Hooks/Spring.js+6 components/src/React/Basic/Hooks/Spring.purs+36 components/src/React/Basic/Hooks/Spring.ts+7 components/src/React/Basic/Hooks/Spring/Spec.purs+25 components/src/React/Basic/Hooks/Spring/Stories.purs+40 components/src/Storybook/React.js+8−25 components/src/Storybook/React.purs+7 components/src/Storybook/React.ts+8 components/src/Yoga/Box/Component.purs+2 components/src/Yoga/InlineCode/Component.purs+4−4 components/src/Yoga/InlineCode/Spec.purs+9−8 components/src/Yoga/InlineCode/Stories.purs+19−19 components/src/Yoga/InlineCode/Styles.purs+1−1 components/src/Yoga/Modal/Stories.purs+1 components/src/Yoga/Modal/Styles.purs+3−2
components/package-lock.json+9
@@ -11655,6 +11655,15 @@
1165511655 "throttle-debounce": "^2.1.0"
1165611656 }
1165711657 },
11658+ "react-spring": {
11659+ "version": "8.0.27",
11660+ "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-8.0.27.tgz",
11661+ "integrity": "sha512-nDpWBe3ZVezukNRandTeLSPcwwTMjNVu1IDq9qA/AMiUqHuRN4BeSWvKr3eIxxg1vtiYiOLy4FqdfCP5IoP77g==",
11662+ "requires": {
11663+ "@babel/runtime": "^7.3.1",
11664+ "prop-types": "^15.5.8"
11665+ }
11666+ },
1165811667 "react-svg-core": {
1165911668 "version": "3.0.3",
1166011669 "resolved": "https://registry.npmjs.org/react-svg-core/-/react-svg-core-3.0.3.tgz",
components/package.json+2−1
@@ -33,7 +33,8 @@
3333 },
3434 "homepage": "https://github.com/i-am-the-slime/psfp#readme",
3535 "dependencies": {
36− "react-jss": "^10.1.1"
36+ "react-jss": "^10.1.1",
37+ "react-spring": "^8.0.27"
3738 },
3839 "devDependencies": {
3940 "@babel/core": "^7.6.0",
components/src/React/Basic/Hooks/Spring.jsnew file+6
@@ -0,0 +1,6 @@
1+"use strict";
2+Object.defineProperty(exports, "__esModule", { value: true });
3+var react_spring_1 = require("react-spring");
4+exports.useSpringImpl = react_spring_1.useSpring;
5+exports.animatedComponentImpl = function (name) { return react_spring_1.animated[name]; };
6+exports.animatedImpl = react_spring_1.animated;
components/src/React/Basic/Hooks/Spring.pursnew file+36
@@ -0,0 +1,36 @@
1+module React.Basic.Hooks.Spring where
2+
3+import Effect.Uncurried (EffectFn1, runEffectFn1)
4+import Prim.Row (class Union)
5+import React.Basic (JSX, ReactComponent, element)
6+import React.Basic.DOM (CSS, Props_div)
7+import React.Basic.Hooks (Hook, unsafeHook)
8+
9+foreign import data UseSpring ∷ Type -> Type -> Type
10+
11+foreign import data SpringStyles ∷ Type
12+
13+foreign import useSpringImpl ∷ EffectFn1 CSS SpringStyles
14+
15+useSpring ∷ CSS -> Hook (UseSpring CSS) SpringStyles
16+useSpring css' = unsafeHook (runEffectFn1 useSpringImpl css')
17+
18+foreign import animatedImpl ∷ ∀ attrs. String -> ReactComponent { | attrs }
19+
20+foreign import animatedComponentImpl ∷ ∀ attrs. ReactComponent { style ∷ CSS | attrs } -> ReactComponent { style ∷ SpringStyles | attrs }
21+
22+animated ∷
23+ ∀ attrs.
24+ ReactComponent { style ∷ CSS | attrs } ->
25+ ReactComponent
26+ { style ∷ SpringStyles
27+ | attrs
28+ }
29+animated = animatedComponentImpl
30+
31+animatedDiv ∷
32+ ∀ attrs attrs_.
33+ Union attrs attrs_ Props_div =>
34+ { style ∷ SpringStyles | attrs } ->
35+ JSX
36+animatedDiv = element (animatedImpl "div")
components/src/React/Basic/Hooks/Spring.tsnew file+7
@@ -0,0 +1,7 @@
1+import { useSpring, animated } from "react-spring";
2+
3+exports.useSpringImpl = useSpring;
4+
5+exports.animatedComponentImpl = (name: string) => animated[name];
6+
7+exports.animatedImpl = animated;
components/src/React/Basic/Hooks/Spring/Spec.pursnew file+25
@@ -0,0 +1,25 @@
1+module React.Basic.Hooks.Spring.Spec where
2+
3+import Prelude
4+import Justifill (justifill)
5+import React.Basic.DOM as R
6+import React.TestingLibrary (describeComponent, renderComponent)
7+import Test.Spec (Spec, it)
8+import Yoga.Stack.Component as Stack
9+
10+spec ∷ Spec Unit
11+spec =
12+ describeComponent Stack.makeComponent
13+ "Springs" do
14+ it "renders without problems" \stack -> do
15+ _ <-
16+ renderComponent stack
17+ ( justifill
18+ { kids:
19+ [ R.h1_ [ R.text "We are stacked" ]
20+ ]
21+ , space: "4rem"
22+ , splitAfter: 7
23+ }
24+ )
25+ pure unit
components/src/React/Basic/Hooks/Spring/Stories.pursnew file+40
@@ -0,0 +1,40 @@
1+module React.Basic.Hooks.Spring.Stories where
2+
3+import Prelude hiding (add)
4+import Data.Tuple.Nested ((/\))
5+import Debug.Trace (spy)
6+import Effect (Effect)
7+import Justifill (justifill)
8+import React.Basic.DOM (css)
9+import React.Basic.DOM as R
10+import React.Basic.Events (handler_)
11+import React.Basic.Helpers (jsx)
12+import React.Basic.Hooks (component, element, fragment, useState)
13+import React.Basic.Hooks as React
14+import React.Basic.Hooks.Spring (animated, animatedDiv, useSpring, useSpringImpl)
15+import Storybook.Decorator.FullScreen (fullScreenDecorator)
16+import Storybook.React (Storybook, add, add_, addDecorator, storiesOf)
17+import Web.DOM.DOMTokenList (toggle)
18+import Yoga.Box.Component as Box
19+import Yoga.Spec.Helpers (withDarkTheme)
20+import Yoga.Stack.Component as Stack
21+
22+stories ∷ Effect Storybook
23+stories = do
24+ storiesOf "Spring" do
25+ add "The Spring" (withDarkTheme mkAnimated)
26+ [ {} ]
27+
28+mkAnimated = do
29+ box <- Box.makeComponent
30+ component "Animated Example" \{} -> React.do
31+ toggled /\ modifyToggled <- useState false
32+ springStyles <- useSpring (css { marginTop: "200px", transform: "scale3d(" <> if toggled then "0.2, 0.2, 1.0" else "10.0, 10.0, 0.0" <> ")" })
33+ pure
34+ $ fragment
35+ [ R.button { children: [ R.text "Toggle" ], onClick: handler_ (modifyToggled not) }
36+ , animatedDiv
37+ { style: springStyles
38+ , children: [ jsx box {} [ R.text "HIIIIIIIIIIIIOOOO" ] ]
39+ }
40+ ]
components/src/Storybook/React.js+8−25
@@ -1,25 +1,8 @@
1−var storybook = require('@storybook/react');
2−
3−exports.storiesOfImpl = function(stories) {
4− return storybook.storiesOf(stories, module.parent);
5−}
6−
7−exports.addImpl = function(sb) {
8− return function(render) {
9− return function(name) {
10− return function() {
11− return sb.add(name, render);
12− }
13− }
14− }
15−}
16−
17−exports.addDecoratorImpl = function(sb) {
18− return function(addDeco) {
19− return function() {
20− return sb.addDecorator(function(storyFn) {
21− return addDeco(storyFn)();
22− });
23− }
24− }
25−}
1+"use strict";
2+Object.defineProperty(exports, "__esModule", { value: true });
3+var storybook = require("@storybook/react");
4+exports.storiesOfImpl = storybook.storiesOf;
5+exports.addImpl = function (sb) { return function (render) { return function (name) { return function () { return sb.add(name, render); }; }; }; };
6+exports.addDecoratorImpl = function (sb) { return function (addDeco) { return function () {
7+ return sb.addDecorator(function (storyFn) { return addDeco(storyFn)(); });
8+}; }; };
components/src/Storybook/React.purs+7
@@ -2,6 +2,7 @@ module Storybook.React
22 ( storiesOf
33 , Storybook
44 , add
5+ , add_
56 , addDecorator
67 ) where
78
@@ -31,6 +32,12 @@ add name mkComponent propsArray = do
3132 newBook <- lift $ addImpl sb component name
3233 local (const newBook) (pure unit)
3334
35+add_ ∷ String -> JSX -> ReaderT Storybook Effect Unit
36+add_ name jsx = do
37+ sb <- ask
38+ newBook <- lift $ addImpl sb (pure jsx) name
39+ local (const newBook) (pure unit)
40+
3441addDecorator ∷ (Effect JSX -> Effect JSX) -> ReaderT Storybook Effect Unit
3542addDecorator decorate = do
3643 sb <- ask
components/src/Storybook/React.tsnew file+8
@@ -0,0 +1,8 @@
1+import storybook = require("@storybook/react");
2+
3+exports.storiesOfImpl = storybook.storiesOf;
4+
5+exports.addImpl = sb => render => name => () => sb.add(name, render);
6+
7+exports.addDecoratorImpl = sb => addDeco => () =>
8+ sb.addDecorator(storyFn => addDeco(storyFn)());
components/src/Yoga/Box/Component.purs+2
@@ -9,6 +9,7 @@ import React.Basic.DOM as R
99import React.Basic.Hooks (ReactComponent, component)
1010import React.Basic.Hooks as React
1111import Record.Extra (pick)
12+import Unsafe.Coerce (unsafeCoerce)
1213import Yoga.Box.Styles (styles)
1314import Yoga.Box.Styles as Styles
1415import Yoga.Helpers (ifJustTrue)
@@ -35,4 +36,5 @@ makeComponent = do
3536 $ R.div
3637 { className: intercalate " " [ classes.box, ifJustTrue props.invert classes.invert, fold className ]
3738 , children: kids
39+ , style: (unsafeCoerce props).style -- Hack for animated components :(
3840 }
components/src/Yoga/InlineCode/Component.purs+4−4
@@ -1,4 +1,4 @@
1−module Yoga.Layer.Component where
1+module Yoga.InlineCode.Component where
22
33import Prelude
44import Data.Foldable (fold, intercalate)
@@ -14,8 +14,8 @@ import React.Basic.Hooks (ReactComponent, component, useState)
1414import React.Basic.Hooks as React
1515import Record.Extra (pick)
1616import Yoga.Helpers ((?||))
17−import Yoga.Layer.Styles (styles)
18−import Yoga.Layer.Styles as Styles
17+import Yoga.InlineCode.Styles (styles)
18+import Yoga.InlineCode.Styles as Styles
1919import Yoga.Theme.Styles (makeStylesJSS)
2020
2121type Props
@@ -37,7 +37,7 @@ type OptionalProps r
3737makeComponent ∷ Effect (ReactComponent Props)
3838makeComponent = do
3939 useStyles <- makeStylesJSS styles
40− component "Layer" \props@{ className, dispatch } -> React.do
40+ component "InlineCode" \props@{ className, dispatch } -> React.do
4141 value /\ modifyValue <- useState ""
4242 classes <- useStyles $ pick props
4343 pure
components/src/Yoga/InlineCode/Spec.purs+9−8
@@ -1,4 +1,4 @@
1−module Yoga.Layer.Spec where
1+module Yoga.InlineCode.Spec where
22
33import Prelude
44import Data.Maybe (Maybe(..))
@@ -17,7 +17,8 @@ import Test.Spec (Spec, it)
1717import Test.Spec.Assertions (shouldEqual)
1818import Web.Event.Internal.Types (Event)
1919import Web.HTML.HTMLElement (focus)
20−import Yoga.Layer.Component as Layer
20+import Yoga.InlineCode.Component as InlineCode
21+import Yoga.Spec.Helpers (withDarkTheme)
2122
2223foreign import newInputEvent ∷ String -> Event
2324
@@ -25,8 +26,8 @@ foreign import newChangeEvent ∷ Event
2526
2627spec ∷ Spec Unit
2728spec =
28− describeComponent mkWrapper
29− "The Layer Component" do
29+ describeComponent (withDarkTheme mkWrapper)
30+ "The InlineCode Component" do
3031 it "renders without problems" \wrapper -> do
3132 strRef <- Ref.new "" # liftEffect
3233 void $ renderComponent wrapper { strRef }
@@ -41,24 +42,24 @@ spec =
4142 refContent `shouldEqual` "Heinzelmän"
4243
4344data Action
44− = LayerAction Layer.Action
45+ = InlineCodeAction InlineCode.Action
4546
4647derive instance eqAction ∷ Eq Action
4748mkReducer ∷ Ref String -> Maybe String -> Action -> Aff (Maybe String)
4849mkReducer ref state = case _ of
49− LayerAction (Layer.CompileAndRunCode s) -> do
50+ InlineCodeAction (InlineCode.CompileAndRunCode s) -> do
5051 Ref.write s ref # liftEffect
5152 pure state
5253
5354mkWrapper ∷ Effect (ReactComponent { strRef ∷ Ref String })
5455mkWrapper = do
55− inlineCode <- Layer.makeComponent
56+ inlineCode <- InlineCode.makeComponent
5657 component "Wrapper" \{ strRef } -> React.do
5758 state /\ dispatch <- useAffReducer Nothing (mkReducer strRef)
5859 useEffect state mempty
5960 pure
6061 $ element inlineCode
6162 ( justifill
62− { dispatch: dispatch <<< LayerAction
63+ { dispatch: dispatch <<< InlineCodeAction
6364 }
6465 )
components/src/Yoga/InlineCode/Stories.purs+19−19
@@ -1,4 +1,4 @@
1−module Yoga.Layer.Stories where
1+module Yoga.InlineCode.Stories where
22
33import Prelude hiding (add)
44import Data.Array (intercalate)
@@ -21,39 +21,39 @@ import React.Basic.Hooks as React
2121import Storybook.Decorator.FullScreen (fullScreenDecorator)
2222import Storybook.React (Storybook, add, addDecorator, storiesOf)
2323import Yoga.CompileEditor.Component (compileAndRun)
24−import Yoga.Layer.Component (Action(..))
25−import Yoga.Layer.Component as Layer
24+import Yoga.InlineCode.Component (Action(..))
25+import Yoga.InlineCode.Component as InlineCode
2626import Yoga.Modal.Component as Modal
2727
2828stories ∷ Effect Storybook
2929stories = do
30− storiesOf "Layer" do
30+ storiesOf "InlineCode" do
3131 addDecorator fullScreenDecorator
32− add "The Layer" Layer.makeComponent
32+ add "The InlineCode" InlineCode.makeComponent
3333 [ ( justifill
34− { dispatch: \(_ ∷ Layer.Action) -> ((log "hi") ∷ Effect Unit)
34+ { dispatch: \(_ ∷ InlineCode.Action) -> ((log "hi") ∷ Effect Unit)
3535 }
3636 )
3737 ]
38− add "The Layer with some context" mkWrapper
38+ add "The InlineCode with some context" mkWrapper
3939 [ { inside:
4040 \inlineCode ->
4141 [ R.text "hi!"
42− , element inlineCode (justifill { dispatch: \(_ ∷ Layer.Action) -> (log "Hi") ∷ Effect Unit })
42+ , element inlineCode (justifill { dispatch: \(_ ∷ InlineCode.Action) -> (log "Hi") ∷ Effect Unit })
4343 , R.text "hello again!"
4444 ]
4545 }
4646 ]
47− add "The Layer with some code" mkWrapper
47+ add "The InlineCode with some code" mkWrapper
4848 [ { inside:
4949 \inlineCode ->
5050 [ R.code_ [ R.text "main = logShow \"" ]
51− , element inlineCode (justifill { dispatch: \(_ ∷ Layer.Action) -> (log "Hi") ∷ Effect Unit })
51+ , element inlineCode (justifill { dispatch: \(_ ∷ InlineCode.Action) -> (log "Hi") ∷ Effect Unit })
5252 , R.code_ [ R.text "\"" ]
5353 ]
5454 }
5555 ]
56− add "The Layer with some real code" mkRealWrapper
56+ add "The InlineCode with some real code" mkRealWrapper
5757 [ {} ]
5858
5959codePrefix =
@@ -69,10 +69,10 @@ renderCode c = intercalate [ R.br {} ] (toJSX <$> lines)
6969 toJSX line = [ R.code_ [ R.text line ] ]
7070 lines = split (Pattern "\n") c
7171
72−mkWrapper ∷ Effect (ReactComponent { inside ∷ ReactComponent Layer.Props -> Array JSX })
72+mkWrapper ∷ Effect (ReactComponent { inside ∷ ReactComponent InlineCode.Props -> Array JSX })
7373mkWrapper = do
74− inlineCode <- Layer.makeComponent
75− component "LayerWrapper" \{ inside } -> React.do
74+ inlineCode <- InlineCode.makeComponent
75+ component "InlineCodeWrapper" \{ inside } -> React.do
7676 pure
7777 $ R.div_ (inside inlineCode)
7878
@@ -80,21 +80,21 @@ type State
8080 = Maybe Boolean
8181
8282data RealAction
83− = LayerAction Layer.Action
83+ = InlineCodeAction InlineCode.Action
8484 | CloseModal
8585
8686derive instance eqRealAction ∷ Eq RealAction
8787mkRealWrapper ∷ Effect (ReactComponent {})
8888mkRealWrapper = do
89− inlineCode <- Layer.makeComponent
89+ inlineCode <- InlineCode.makeComponent
9090 modal <- Modal.makeComponent
91− component "LayerWrapper" \{} -> React.do
91+ component "InlineCodeWrapper" \{} -> React.do
9292 state /\ dispatch <- useAffReducer Nothing realReducer
9393 pure
9494 $ R.div_
9595 [ R.h2_ [ R.text "Let's log some 'Magick'" ]
9696 , fragment $ renderCode codePrefix
97− , element inlineCode (justifill { dispatch: dispatch <<< LayerAction, width: String.length "Magick" })
97+ , element inlineCode (justifill { dispatch: dispatch <<< InlineCodeAction, width: String.length "Magick" })
9898 , fragment $ renderCode codeSuffix
9999 , R.br {}
100100 , case state of
@@ -106,7 +106,7 @@ mkRealWrapper = do
106106realReducer ∷ State -> RealAction -> Aff State
107107realReducer state = case _ of
108108 CloseModal -> pure Nothing
109− LayerAction (CompileAndRunCode code) -> do
109+ InlineCodeAction (CompileAndRunCode code) -> do
110110 res <- compileAndRun (M.fetch windowFetch) { code: codePrefix <> code <> codeSuffix }
111111 (pure <<< pure) case res of
112112 Right { stdout }
components/src/Yoga/InlineCode/Styles.purs+1−1
@@ -1,4 +1,4 @@
1−module Yoga.Layer.Styles where
1+module Yoga.InlineCode.Styles where
22
33import Prelude
44import CSS (GenericFontFamily(..), Selector, TimingFunction(..), animation, background, border, borderBottom, borderBox, borderRadius, boxSizing, color, darken, display, element, focus, fontFamily, fontSize, fromString, inlineBlock, iterationCount, keyframes, lighten, lineHeight, nil, padding, sec, solid, transform, transition, unitless, width, (!*), (!+), (&), (?))
components/src/Yoga/Modal/Stories.purs+1
@@ -12,6 +12,7 @@ import React.Basic.Events (handler_)
1212import React.Basic.Helpers (jsx)
1313import React.Basic.Hooks (ReactComponent, component, element, fragment, useState)
1414import React.Basic.Hooks as React
15+import React.Basic.Hooks.Spring (animatedDiv, useSpring)
1516import Storybook.Decorator.FullScreen (fullScreenDecorator)
1617import Storybook.React (Storybook, add, addDecorator, storiesOf)
1718import Yoga.Button.Component (mkButton)
components/src/Yoga/Modal/Styles.purs+3−2
@@ -1,8 +1,9 @@
11module Yoga.Modal.Styles where
22
33import Prelude hiding (top)
4−import CSS (backgroundColor, borderRadius, boxShadow, nil, rem, toHexString)
4+import CSS (backgroundColor, borderRadius, boxShadow, nil, opacity, rem, toHexString, transform, transforms, transition)
55import CSS as Color
6+import CSS.Transform (scaleZ)
67import JSS (JSSClasses, JSSElem, jssClasses)
78import Yoga.Theme.Types (YogaTheme)
89
@@ -44,7 +45,7 @@ styles =
4445 boxShadow nil nil (3.5 # rem) (Color.rgba 0 0 0 0.5)
4546 borderRadius boxBorderRadius boxBorderRadius boxBorderRadius boxBorderRadius
4647 , closeIcon:
47− { fill: theme.textColour
48+ { fill: theme.red
4849 , width: "calc(0.8em * var(--ratio))"
4950 , height: "calc(0.8em * var(--ratio))"
5051 , margin: 0