git.iko.soy/rowtype-yoga/psfp
on master help sign in
Draggable Spells
4669fb5Mark Eibes
assets/icons/elements.afdesignnew file

Binary file not shown.

components/src/React/Basic/Helpers.purs+14−7
@@ -1,6 +1,7 @@
1module React.Basic.Helpers where
1module React.Basic.Helpers where
2
2
3+import Prelude
3−import Data.Maybe (Maybe, fromMaybe, fromMaybe')
4+import Data.Maybe (Maybe, fromMaybe')
4import Data.Symbol (SProxy(..))
5import Data.Symbol (SProxy(..))
5import Justifill.Fillable (class Fillable, class FillableFields, fill)
6import Justifill.Fillable (class Fillable, class FillableFields, fill)
6import Justifill.Justifiable (class Justifiable, justify)
7import Justifill.Justifiable (class Justifiable, justify)
@@ -8,6 +9,7 @@ import Literals.Undefined (undefined)
8import Prim.Row (class Lacks, class Nub)
9import Prim.Row (class Lacks, class Nub)
9import Prim.RowList (class RowToList)
10import Prim.RowList (class RowToList)
10import React.Basic (JSX)
11import React.Basic (JSX)
12+import React.Basic.DOM as R
11import React.Basic.Hooks (ReactComponent, element)
13import React.Basic.Hooks (ReactComponent, element)
12import Record (disjointUnion, insert)
14import Record (disjointUnion, insert)
13import Unsafe.Coerce (unsafeCoerce)
15import Unsafe.Coerce (unsafeCoerce)
@@ -57,13 +59,18 @@ jsx x partialProps kids = element x propsWithKids
57 where
59 where
58 propsWithKids ∷ Record (Kids to)
60 propsWithKids ∷ Record (Kids to)
59 propsWithKids = disjointUnion { kids } props
61 propsWithKids = disjointUnion { kids } props
62+ fill' ∷ { | thru } -> { | to }
63+ fill' = fill
64+ justify' ∷ { | from } -> { | thru }
65+ justify' = justify
60 props ∷ Record to
66 props ∷ Record to
61− props =
62− ( (fill ∷ { | thru } -> { | to })
63− ( (justify ∷ { | from } -> { | thru })
64− partialProps
67+ props = fill' (justify' partialProps)
65− )
66− )
67
68
68orUndefined ∷ ∀ a. Maybe a -> a
69orUndefined ∷ ∀ a. Maybe a -> a
69orUndefined = fromMaybe' \_ -> unsafeCoerce undefined
70orUndefined = fromMaybe' \_ -> unsafeCoerce undefined
71+
72+classSpan ∷ String -> Array JSX -> JSX
73+classSpan className children = R.span { className, children }
74+
75+classDiv ∷ String -> Array JSX -> JSX
76+classDiv className children = R.div { className, children }
components/src/React/Basic/Hooks/Spring.js+5
@@ -5,6 +5,11 @@ exports.useSpringImpl = function (mkStyles) { return function () {
5 var result = react_spring_1.useSpring(mkStyles);
5 var result = react_spring_1.useSpring(mkStyles);
6 return { style: result[0], set: result[1], stop: result[2] };
6 return { style: result[0], set: result[1], stop: result[2] };
7}; };
7}; };
8+exports.useSpringsImpl = function (n) { return function (fn) { return function () {
9+ var result = react_spring_1.useSprings(n, fn);
10+ console.log("REEEEEEEEESLUT", result);
11+ return { styles: result[0], set: result[1], stop: result[2] };
12+}; }; };
8exports.useTransitionImpl = react_spring_1.useTransition;
13exports.useTransitionImpl = react_spring_1.useTransition;
9exports.animatedComponentImpl = function (name) { return react_spring_1.animated[name]; };
14exports.animatedComponentImpl = function (name) { return react_spring_1.animated[name]; };
10exports.animatedImpl = react_spring_1.animated;
15exports.animatedImpl = react_spring_1.animated;
components/src/React/Basic/Hooks/Spring.purs+23−3
@@ -6,14 +6,12 @@ import Data.Nullable (Nullable, toNullable)
6import Data.Nullable as Nullable
6import Data.Nullable as Nullable
7import Effect (Effect)
7import Effect (Effect)
8import Effect.Uncurried (EffectFn1, EffectFn3, runEffectFn1, runEffectFn3)
8import Effect.Uncurried (EffectFn1, EffectFn3, runEffectFn1, runEffectFn3)
9−import Foreign (Foreign)
10import Prim.Row (class Union)
9import Prim.Row (class Union)
11−import React.Basic (JSX, ReactComponent, Ref, element)
10+import React.Basic (JSX, ReactComponent, element)
12import React.Basic.DOM (CSS, Props_div, Props_span)
11import React.Basic.DOM (CSS, Props_div, Props_span)
13import React.Basic.DOM.SVG (Props_svg, Props_path)
12import React.Basic.DOM.SVG (Props_svg, Props_path)
14import React.Basic.Hooks (Hook, unsafeHook)
13import React.Basic.Hooks (Hook, unsafeHook)
15import React.Basic.Hooks as React
14import React.Basic.Hooks as React
16−import Simple.JSON (class WriteForeign)
17
15
18foreign import data UseSpring ∷ Type -> Type -> Type
16foreign import data UseSpring ∷ Type -> Type -> Type
19
17
@@ -33,6 +31,28 @@ useSpring f = React.do
33 res <- unsafeHook (useSpringImpl f)
31 res <- unsafeHook (useSpringImpl f)
34 pure $ res { set = runEffectFn1 res.set }
32 pure $ res { set = runEffectFn1 res.set }
35
33
34+foreign import data UseSprings ∷ Type -> Type -> Type
35+
36+foreign import useSpringsImpl ∷
37+ ∀ r s.
38+ Int ->
39+ (Int -> { | r }) ->
40+ Effect { styles ∷ Array { | r }, set ∷ SetSpringsImpl s, stop ∷ StopSpring }
41+
42+type SetSpringsImpl r
43+ = EffectFn1 (Int -> { | r }) Unit
44+
45+type SetSprings r
46+ = (Int -> { | r }) -> Effect Unit
47+
48+useSprings ∷
49+ ∀ r s.
50+ Int ->
51+ (Int -> { | r }) -> Hook (UseSprings { | r }) { styles ∷ Array { | r }, set ∷ SetSprings s, stop ∷ StopSpring }
52+useSprings n f = React.do
53+ res <- unsafeHook (useSpringsImpl n f)
54+ pure $ res { set = runEffectFn1 res.set }
55+
36foreign import data UseTransition ∷ Type -> Type -> Type
56foreign import data UseTransition ∷ Type -> Type -> Type
37
57
38foreign import useTransitionImpl ∷ ∀ a. EffectFn3 (Array a) (Nullable (a -> String)) CSS (Array { item ∷ Nullable a, key ∷ Nullable String, props ∷ CSS })
58foreign import useTransitionImpl ∷ ∀ a. EffectFn3 (Array a) (Nullable (a -> String)) CSS (Array { item ∷ Nullable a, key ∷ Nullable String, props ∷ CSS })
components/src/React/Basic/Hooks/Spring.ts+15−1
@@ -1,10 +1,24 @@
1+import {
2+ useChain,
3+ useSpring,
4+ useSprings,
5+ useTransition,
6+ interpolate,
7+ animated,
1−import { useChain, useSpring, useTransition, animated } from "react-spring";
8+} from "react-spring";
9+
10+exports.interpolateImpl = interpolate;
2
11
3exports.useSpringImpl = (mkStyles) => () => {
12exports.useSpringImpl = (mkStyles) => () => {
4 const result = useSpring(mkStyles);
13 const result = useSpring(mkStyles);
5 return { style: result[0], set: result[1], stop: result[2] };
14 return { style: result[0], set: result[1], stop: result[2] };
6};
15};
7
16
17+exports.useSpringsImpl = (n: number) => (fn) => () => {
18+ const result = useSprings(n, fn);
19+ return { styles: result[0], set: result[1], stop: result[2] };
20+};
21+
8exports.useTransitionImpl = useTransition;
22exports.useTransitionImpl = useTransition;
9
23
10exports.animatedComponentImpl = (name: string) => animated[name];
24exports.animatedComponentImpl = (name: string) => animated[name];
components/src/React/Basic/Hooks/Spring/Stories.purs+4−3
@@ -7,6 +7,7 @@ import Data.Monoid (guard)
7import Data.Tuple.Nested ((/\))
7import Data.Tuple.Nested ((/\))
8import Effect (Effect)
8import Effect (Effect)
9import JSS (jssClasses)
9import JSS (jssClasses)
10+import Justifill (justifill)
10import React.Basic.DOM (css)
11import React.Basic.DOM (css)
11import React.Basic.DOM as R
12import React.Basic.DOM as R
12import React.Basic.Events (handler_)
13import React.Basic.Events (handler_)
@@ -129,8 +130,8 @@ mkDragAnimated = do
129 component "Draggable Example" \{} -> React.do
130 component "Draggable Example" \{} -> React.do
130 { style, set } <- useSpring $ const { x: 0.0, y: 0.0, config: { mass: 1, tension: 210, friction: 20 } }
131 { style, set } <- useSpring $ const { x: 0.0, y: 0.0, config: { mass: 1, tension: 210, friction: 20 } }
131 classes <- useStyles {}
132 classes <- useStyles {}
132− mkDragProps <-
133+ bindDragProps <-
133− useDrag \{ down, movement: mx /\ my } ->
134+ useDrag (justifill {}) \{ down, movement: mx /\ my } ->
134 set { x: if down then mx else 0.0, y: if down then my else 0.0 }
135 set { x: if down then mx else 0.0, y: if down then my else 0.0 }
135 pure
136 pure
136 $ animatedDiv
137 $ animatedDiv
@@ -140,4 +141,4 @@ mkDragAnimated = do
140 ]
141 ]
141 }
142 }
142 `withDragProps`
143 `withDragProps`
143− mkDragProps
144+ (bindDragProps unit)
components/src/React/Basic/Hooks/UseGesture.purs+37−16
@@ -2,40 +2,61 @@ module React.Basic.Hooks.UseGesture where
2
2
3import Prelude
3import Prelude
4import Data.Array ((!!))
4import Data.Array ((!!))
5−import Data.Foldable (fold)
5+import Data.Maybe (Maybe, fromMaybe')
6−import Data.Monoid.Additive (Additive(..))
7−import Data.Newtype (ala)
6+import Data.Nullable (Nullable)
8import Data.Tuple.Nested ((/\), type (/\))
7import Data.Tuple.Nested ((/\), type (/\))
8+import Debug.Trace (spy)
9import Effect (Effect)
9import Effect (Effect)
10−import Effect.Uncurried (EffectFn1, runEffectFn1)
10+import Effect.Aff.Compat (runEffectFn2)
11+import Effect.Uncurried (EffectFn2)
11import Effect.Unsafe (unsafePerformEffect)
12import Effect.Unsafe (unsafePerformEffect)
13+import Partial.Unsafe (unsafeCrashWith)
12import Prim.Row (class Lacks, class Nub)
14import Prim.Row (class Lacks, class Nub)
13import React.Basic.Events (EventHandler)
15import React.Basic.Events (EventHandler)
16+import React.Basic.Helpers (orUndefined)
14−import React.Basic.Hooks (Hook, unsafeHook)
17+import React.Basic.Hooks (Hook, Ref, unsafeHook)
15import Record (disjointUnion)
18import Record (disjointUnion)
19+import Web.DOM (Node)
16import Yoga.Helpers ((?||))
20import Yoga.Helpers ((?||))
17
21
18foreign import data UseDrag ∷ Type -> Type -> Type
22foreign import data UseDrag ∷ Type -> Type -> Type
19
23
20−type DragHandler
24+type DragHandler a
21− = { down ∷ Boolean, movement ∷ Number /\ Number } -> Effect Unit
25+ = { arg ∷ a, down ∷ Boolean, movement ∷ Number /\ Number } -> Effect Unit
22
26
23−type DragHandlerImpl
27+type DragHandlerImpl a
24− = { down ∷ Boolean, movement ∷ Array Number } -> Unit
28+ = { args ∷ Array a, down ∷ Boolean, movement ∷ Array Number } -> Unit
25
29
26type DragProps
30type DragProps
27 = { onMouseDown ∷ EventHandler, onTouchStart ∷ EventHandler }
31 = { onMouseDown ∷ EventHandler, onTouchStart ∷ EventHandler }
28
32
29−foreign import useDragImpl ∷ EffectFn1 DragHandlerImpl (Effect DragProps)
33+type GenericOptionsImpl r
34+ = { domTarget ∷ Ref (Nullable Node) | r }
30
35
36+type GenericOptions r
37+ = { domTarget ∷ Maybe (Ref (Nullable Node)) | r }
38+
39+type DragOptions
40+ = GenericOptions ()
41+
42+type DragOptionsImpl
43+ = GenericOptionsImpl ()
44+
45+dragOptionsToImpl ∷ DragOptions -> DragOptionsImpl
46+dragOptionsToImpl { domTarget } = { domTarget: domTarget # orUndefined }
47+
48+foreign import useDragImpl ∷ ∀ a. EffectFn2 (DragHandlerImpl a) DragOptionsImpl (a -> DragProps)
49+
31−useDrag ∷ DragHandler -> Hook (UseDrag Unit) (Effect DragProps)
50+useDrag ∷ ∀ a. DragOptions -> DragHandler a -> Hook (UseDrag Unit) (a -> DragProps)
32−useDrag dragHandler = unsafeHook (runEffectFn1 useDragImpl f)
51+useDrag dragOptions dragHandler = unsafeHook (runEffectFn2 useDragImpl dragHandlerImpl (dragOptionsToImpl dragOptions))
33 where
52 where
34− f x =
53+ dragHandlerImpl ∷ DragHandlerImpl a
54+ dragHandlerImpl x =
35 (unsafePerformEffect <<< dragHandler)
55 (unsafePerformEffect <<< dragHandler)
36− { down: x.down, movement: mx /\ my
56+ { arg, down: x.down, movement: mx /\ my
37 }
57 }
38 where
58 where
59+ arg = x.args !! 0 # fromMaybe' (\_ -> unsafeCrashWith "Bollox")
39 mx = x.movement !! 0 ?|| 0.0
60 mx = x.movement !! 0 ?|| 0.0
40 my = x.movement !! 1 ?|| 0.0
61 my = x.movement !! 1 ?|| 0.0
41
62
@@ -47,6 +68,6 @@ withDragProps ∷
47 ( onMouseDown ∷ EventHandler, onTouchStart ∷ EventHandler | attrs )
68 ( onMouseDown ∷ EventHandler, onTouchStart ∷ EventHandler | attrs )
48 ( onMouseDown ∷ EventHandler, onTouchStart ∷ EventHandler | attrs ) =>
69 ( onMouseDown ∷ EventHandler, onTouchStart ∷ EventHandler | attrs ) =>
49 { | attrs } ->
70 { | attrs } ->
50− Effect DragProps ->
71+ DragProps ->
51 { onMouseDown ∷ EventHandler, onTouchStart ∷ EventHandler | attrs }
72 { onMouseDown ∷ EventHandler, onTouchStart ∷ EventHandler | attrs }
52−withDragProps x (y ∷ Effect DragProps) = disjointUnion (unsafePerformEffect y) x
73+withDragProps x (y ∷ DragProps) = disjointUnion y x
components/src/Storybook/Decorator/FullScreen.purs+10−1
@@ -112,5 +112,14 @@ mkThemeSwitcher = do
112 pure
112 pure
113 $ element themeProvider
113 $ element themeProvider
114 { theme
114 { theme
115+ , children:
115− , children: [ element baseline { kids: [ R.div_ [ themeSelect, child ] ] } ]
116+ [ element baseline
117+ { kids:
118+ [ R.div
119+ { style: css { width: "100%" }
120+ , children: [ themeSelect, child ]
121+ }
122+ ]
123+ }
124+ ]
116 }
125 }
components/src/Yoga/Card/Component.purs+13−9
@@ -6,13 +6,16 @@ import Color as Color
6import Data.Foldable (fold)
6import Data.Foldable (fold)
7import Data.Interpolate (i)
7import Data.Interpolate (i)
8import Data.Maybe (Maybe)
8import Data.Maybe (Maybe)
9+import Data.Nullable (Nullable)
9import Effect (Effect)
10import Effect (Effect)
10import JSS (JSSClasses, JSSElem, jssClasses)
11import JSS (JSSClasses, JSSElem, jssClasses)
11import React.Basic (JSX)
12import React.Basic (JSX)
12import React.Basic.DOM as R
13import React.Basic.DOM as R
14+import React.Basic.Helpers (orUndefined)
13−import React.Basic.Hooks (ReactComponent, component)
15+import React.Basic.Hooks (ReactComponent, Ref, component)
14import React.Basic.Hooks as React
16import React.Basic.Hooks as React
15import Record.Extra (pick)
17import Record.Extra (pick)
18+import Web.DOM (Node)
16import Yoga.Box.Component as Box
19import Yoga.Box.Component as Box
17import Yoga.Helpers (ifJustTrue)
20import Yoga.Helpers (ifJustTrue)
18import Yoga.Theme (withAlpha)
21import Yoga.Theme (withAlpha)
@@ -44,24 +47,25 @@ styles =
44 }
47 }
45 }
48 }
46
49
47−type Props r
50+type PropsR r
48 = ( kids ∷ Array JSX
51 = ( kids ∷ Array JSX
49 , className ∷ Maybe String
52 , className ∷ Maybe String
53+ , divRef ∷ Maybe (Ref (Nullable Node))
50 | r
54 | r
51 )
55 )
52
56
53−mkCard ∷
57+type Props
54− Effect
55− ( ReactComponent
56− { | Props (StyleProps) }
58+ = { | PropsR (StyleProps) }
57− )
59+
60+mkCard ∷ Effect (ReactComponent Props)
58mkCard = do
61mkCard = do
59 useStyles <- makeStylesJSS styles
62 useStyles <- makeStylesJSS styles
60 box <- Box.makeComponent
63 box <- Box.makeComponent
61− component "Card" \props@{ kids, className } -> React.do
64+ component "Card" \(props@{ kids, className } ∷ Props) -> React.do
62 classes <- useStyles (pick props)
65 classes <- useStyles (pick props)
63 pure
66 pure
64 $ R.div
67 $ R.div
68+ { ref: props.divRef # orUndefined
65− { className: classes.card <> " " <> fold className
69+ , className: classes.card <> " " <> fold className
66 , children: kids
70 , children: kids
67 }
71 }
components/src/Yoga/Cover/Component.purs+9−19
@@ -2,15 +2,14 @@ module Yoga.Cover.Component where
2
2
3import Prelude
3import Prelude
4import Data.Array (foldMap)
4import Data.Array (foldMap)
5+import Data.Array as Array
5import Data.Maybe (Maybe)
6import Data.Maybe (Maybe)
6import Effect (Effect)
7import Effect (Effect)
7−import Yoga.Cover.Styles as Cover
8−import Prim.Row (class Nub, class Union)
9import React.Basic (JSX)
8import React.Basic (JSX)
10import React.Basic.DOM as R
9import React.Basic.DOM as R
11import React.Basic.Hooks (ReactComponent, component)
10import React.Basic.Hooks (ReactComponent, component)
12import React.Basic.Hooks as React
11import React.Basic.Hooks as React
13−import Record (disjointUnion)
12+import Yoga.Cover.Styles as Cover
14import Yoga.Theme.Styles (makeStylesJSS)
13import Yoga.Theme.Styles (makeStylesJSS)
15
14
16type Props
15type Props
@@ -20,33 +19,24 @@ type PropsR
20 = OptionalProps ()
19 = OptionalProps ()
21
20
22type OptionalProps r
21type OptionalProps r
23− = ( header ∷ JSX
22+ = ( header ∷ Maybe JSX
24− , footer ∷ JSX
23+ , footer ∷ Maybe JSX
25− , principal ∷ JSX
24+ , kids ∷ Array JSX
26 , className ∷ Maybe String
25 , className ∷ Maybe String
27 | r
26 | r
28 )
27 )
29
28
30−withDefaults ∷
31− ∀ r missing props.
32− Union r missing props =>
33− Nub props props =>
34− Monoid { | missing } =>
35− { | r } ->
36− { | props }
37−withDefaults x = disjointUnion x mempty
38−
39makeComponent ∷ Effect (ReactComponent Props)
29makeComponent ∷ Effect (ReactComponent Props)
40makeComponent = do
30makeComponent = do
41 useStyles <- makeStylesJSS Cover.styles
31 useStyles <- makeStylesJSS Cover.styles
42− component "Cover" \{ header, footer, principal, className } -> React.do
32+ component "Cover" \{ header, footer, kids, className } -> React.do
43 classes <- useStyles {}
33 classes <- useStyles {}
44 pure
34 pure
45 $ R.div
35 $ R.div
46 { className: classes.cover <> foldMap (" " <> _) className
36 { className: classes.cover <> foldMap (" " <> _) className
47 , children:
37 , children:
48− [ R.div { className: classes.header, children: pure header }
38+ [ R.div { className: classes.header, children: Array.fromFoldable header }
49− , R.div { className: classes.principal, children: pure principal }
39+ , R.div { className: classes.principal, children: kids }
50− , R.div { className: classes.footer, children: pure footer }
40+ , R.div { className: classes.footer, children: Array.fromFoldable footer }
51 ]
41 ]
52 }
42 }
components/src/Yoga/Cover/Spec.purs+6−4
@@ -1,14 +1,16 @@
1module Yoga.Cover.Spec where
1module Yoga.Cover.Spec where
2
2
3import Prelude
3import Prelude
4−import Yoga.Cover.Component as Cover
4+import Justifill (justifill)
5+import React.Basic.DOM as R
5import React.TestingLibrary (describeComponent, renderComponent)
6import React.TestingLibrary (describeComponent, renderComponent)
6import Test.Spec (Spec, it)
7import Test.Spec (Spec, it)
8+import Yoga.Cover.Component as Cover
7
9
8−spec :: Spec Unit
10+spec ∷ Spec Unit
9spec =
11spec =
10 describeComponent Cover.makeComponent
12 describeComponent Cover.makeComponent
11 "The Cover Component" do
13 "The Cover Component" do
12− it "renders without problems" \panel -> do
14+ it "renders without problems" \cover -> do
13− _ <- renderComponent panel (Cover.withDefaults {})
15+ _ <- renderComponent cover (justifill { kids: [ R.text "hi" ] })
14 pure unit
16 pure unit
components/src/Yoga/Cover/Stories.purs+12−8
@@ -1,30 +1,34 @@
1module Yoga.Cover.Stories where
1module Yoga.Cover.Stories where
2
2
3import Prelude hiding (add)
3import Prelude hiding (add)
4−import Storybook.Decorator.FullScreen (fullScreenDecorator)
5import Effect (Effect)
4import Effect (Effect)
6−import Yoga.Cover.Component as Cover
5+import Justifill (justifill)
6+import React.Basic (JSX)
7import React.Basic.DOM as R
7import React.Basic.DOM as R
8+import Storybook.Decorator.FullScreen (fullScreenDecorator)
8import Storybook.React (Storybook, add, addDecorator, storiesOf)
9import Storybook.React (Storybook, add, addDecorator, storiesOf)
10+import Yoga.Cover.Component as Cover
9
11
10stories ∷ Effect Storybook
12stories ∷ Effect Storybook
11stories = do
13stories = do
12 storiesOf "Cover" do
14 storiesOf "Cover" do
13 addDecorator fullScreenDecorator
15 addDecorator fullScreenDecorator
14 add "The Cover" Cover.makeComponent
16 add "The Cover" Cover.makeComponent
15− [ Cover.withDefaults
17+ [ justifill
16− { principal: R.h1_ [ R.text "Main thing" ]
18+ { kids: [ R.h1_ [ R.text "Main thing" ] ]
17 , header: R.text "Header"
19 , header: R.text "Header"
18 , footer: R.text "Footer"
20 , footer: R.text "Footer"
19 }
21 }
20− , Cover.withDefaults
22+ , justifill
21− { principal: R.h1_ [ R.text "Only main" ]
23+ { kids: [ R.h1_ [ R.text "Only main" ] ]
22 }
24 }
23− , Cover.withDefaults
25+ , justifill
24 { header: R.h1_ [ R.text "Only header" ]
26 { header: R.h1_ [ R.text "Only header" ]
27+ , kids: [] ∷ Array JSX
25 }
28 }
26− , Cover.withDefaults
29+ , justifill
27 { header: R.h1_ [ R.text "Header" ]
30 { header: R.h1_ [ R.text "Header" ]
28 , footer: R.h1_ [ R.text "Footer" ]
31 , footer: R.h1_ [ R.text "Footer" ]
32+ , kids: [] ∷ Array JSX
29 }
33 }
30 ]
34 ]
components/src/Yoga/Grid/Spec.purs+2−1
@@ -3,6 +3,7 @@ module Yoga.Grid.Spec where
3import Prelude
3import Prelude
4import Justifill (justifill)
4import Justifill (justifill)
5import React.Basic.DOM as R
5import React.Basic.DOM as R
6+import React.Basic.Hooks (JSX)
6import React.TestingLibrary (describeComponent, renderComponent)
7import React.TestingLibrary (describeComponent, renderComponent)
7import Test.Spec (Spec, it)
8import Test.Spec (Spec, it)
8import Yoga.Grid.Component as Grid
9import Yoga.Grid.Component as Grid
@@ -16,5 +17,5 @@ spec =
16 _ <-
17 _ <-
17 renderComponent grid
18 renderComponent grid
18 $ justifill
19 $ justifill
19− {}
20+ { kids: [] ∷ _ JSX }
20 pure unit
21 pure unit
components/src/Yoga/Grid/Stories.purs+1−3
@@ -1,9 +1,8 @@
1module Yoga.Grid.Stories where
1module Yoga.Grid.Stories where
2
2
3import Prelude hiding (add)
3import Prelude hiding (add)
4−import Data.Array (mapWithIndex, replicate, (..))
4+import Data.Array ((..))
5import Effect (Effect)
5import Effect (Effect)
6−import Effect.Unsafe (unsafePerformEffect)
7import Justifill (justifill)
6import Justifill (justifill)
8import React.Basic.DOM (css)
7import React.Basic.DOM (css)
9import React.Basic.DOM as R
8import React.Basic.DOM as R
@@ -15,7 +14,6 @@ import Yoga.Box.Component as Box
15import Yoga.Card.Component (mkCard)
14import Yoga.Card.Component (mkCard)
16import Yoga.Centre.Component as Centre
15import Yoga.Centre.Component as Centre
17import Yoga.Grid.Component as Grid
16import Yoga.Grid.Component as Grid
18−import Yoga.Stack.Component as Stack
19
17
20stories ∷ Effect Storybook
18stories ∷ Effect Storybook
21stories = do
19stories = do
components/src/Yoga/Grimoire/Component.jsnew file+4
@@ -0,0 +1,4 @@
1+exports.unsafeArraySetAt = function (i) { return function (v) { return function (arr) {
2+ arr[i] = v;
3+ return arr;
4+}; }; };
components/src/Yoga/Grimoire/Component.purs+52−5
@@ -1,25 +1,72 @@
1module Yoga.Grimoire.Component where
1module Yoga.Grimoire.Component where
2
2
3import Prelude
3import Prelude
4+import Data.Array (mapWithIndex, zip)
5+import Data.Array as Array
6+import Data.Maybe (Maybe(..))
7+import Data.Nullable (Nullable)
8+import Data.Tuple.Nested ((/\))
9+import Debug.Trace (spy)
4import Effect (Effect)
10import Effect (Effect)
11+import Justifill (justifill)
5import React.Basic (ReactComponent)
12import React.Basic (ReactComponent)
6−import React.Basic.DOM as R
13+import React.Basic.DOM (css)
14+import React.Basic.Helpers (jsx)
7−import React.Basic.Hooks (component)
15+import React.Basic.Hooks (Ref, component, element)
8import React.Basic.Hooks as React
16import React.Basic.Hooks as React
17+import React.Basic.Hooks.Spring (animatedDiv, useSprings)
18+import React.Basic.Hooks.UseGesture (useDrag, withDragProps)
9import Record.Extra (pick)
19import Record.Extra (pick)
20+import Unsafe.Coerce (unsafeCoerce)
21+import Web.DOM (Node)
22+import Yoga.Grid.Component as Grid
23+import Yoga.Grimoire.Spell.Component as GrimoireSpell
10import Yoga.Grimoire.Styles (styles)
24import Yoga.Grimoire.Styles (styles)
25+import Yoga.Spell.Types (Spell)
11import Yoga.Theme.Styles (makeStylesJSS, useTheme)
26import Yoga.Theme.Styles (makeStylesJSS, useTheme)
12import Yoga.Theme.Types (CSSTheme)
27import Yoga.Theme.Types (CSSTheme)
13
28
14type Props
29type Props
15− = {
30+ = { spells ∷ Array Spell
16 }
31 }
17
32
18makeComponent ∷ Effect (ReactComponent Props)
33makeComponent ∷ Effect (ReactComponent Props)
19makeComponent = do
34makeComponent = do
35+ grid <- Grid.makeComponent
36+ spellComponent <- GrimoireSpell.makeComponent
20 useStyles <- makeStylesJSS styles
37 useStyles <- makeStylesJSS styles
21− component "Grimoire" \(props@{} ∷ Props) -> React.do
38+ component "Grimoire" \(props ∷ Props) -> React.do
22 {} <- useStyles (pick props)
39 {} <- useStyles (pick props)
40+ springs <- useSprings (Array.length props.spells) \_ -> { x: 0.0, y: 0.0, zIndex: 0, immediate: false, transform: "scale3d(1.0,1.0,1.0)" }
41+ let
42+ _ = spy "springs" springs
23 theme ∷ CSSTheme <- useTheme
43 theme ∷ CSSTheme <- useTheme
44+ bindDragProps <-
45+ useDrag (justifill {}) \{ arg, down, movement: mx /\ my } -> do
46+ springs.set \i ->
47+ if i == arg && down then
48+ { x: mx, y: my, zIndex: 1, transform: "scale3d(1.1, 1.1, 1.1)", immediate: \n -> n == "x" || n == "y" || n == "zIndex" }
49+ else
50+ { x: 0.0, y: 0.0, zIndex: 0, transform: "scale3d(1.0, 1.0, 1.0)", immediate: const false }
51+ let
52+ renderSpells =
53+ mapWithIndex \i (spell /\ style) ->
54+ animatedDiv
55+ $ { style: css style
56+ , children:
57+ [ element
58+ spellComponent
59+ { spell
60+ , cardRef: Nothing
61+ }
62+ ]
63+ }
64+ `withDragProps`
65+ bindDragProps i
24 pure
66 pure
25− $ R.div_ [ R.text "WriteMe" ]
67+ $ jsx grid {} (renderSpells (props.spells `zip` springs.styles))
68+
69+foreign import unsafeArraySetAt ∷ ∀ a. Int -> a -> Array a -> Array a
70+
71+unsafeUpdateRefs ∷ Ref (Array (Nullable Node)) -> Int -> Nullable Node -> Array (Nullable Node)
72+unsafeUpdateRefs refsRef i el = unsafeArraySetAt i el ((unsafeCoerce refsRef).current)
components/src/Yoga/Grimoire/Component.tsnew file+4
@@ -0,0 +1,4 @@
1+exports.unsafeArraySetAt = <A>(i: number) => (v: A) => (arr: Array<A>) => {
2+ arr[i] = v;
3+ return arr;
4+};
components/src/Yoga/Grimoire/Spell/Component.pursnew file+66
@@ -0,0 +1,66 @@
1+module Yoga.Grimoire.Spell.Component where
2+
3+import Prelude
4+import CSS (AlignItemsValue, JustifyContentValue, spaceBetween)
5+import CSS.Common (baseline)
6+import Data.Maybe (Maybe)
7+import Data.Nullable (Nullable)
8+import Effect (Effect)
9+import React.Basic (ReactComponent)
10+import React.Basic.DOM as R
11+import React.Basic.Helpers (classSpan, jsx)
12+import React.Basic.Hooks (Ref, component)
13+import React.Basic.Hooks as React
14+import Record.Extra (pick)
15+import Web.DOM (Node)
16+import Yoga.Box.Component as Box
17+import Yoga.Card.Component (mkCard)
18+import Yoga.Centre.Component as Centre
19+import Yoga.Cluster.Component as Cluster
20+import Yoga.Cover.Component as Cover
21+import Yoga.Grimoire.Spell.Styles (styles)
22+import Yoga.Grimoire.Spell.Styles as Style
23+import Yoga.Spell.Types (Spell)
24+import Yoga.Stack.Component as Stack
25+import Yoga.Theme.Styles (makeStylesJSS, useTheme)
26+import Yoga.Theme.Types (CSSTheme)
27+
28+type Props
29+ = { spell ∷ Spell
30+ , cardRef ∷ Maybe (Ref (Nullable Node))
31+ | Style.PropsR
32+ }
33+
34+makeComponent ∷ Effect (ReactComponent Props)
35+makeComponent = do
36+ box <- Box.makeComponent
37+ centre <- Centre.makeComponent
38+ stack <- Stack.makeComponent
39+ cluster <- Cluster.makeComponent
40+ card <- mkCard
41+ cover <- Cover.makeComponent
42+ useStyles <- makeStylesJSS styles
43+ component "Spell" \(props@{ spell } ∷ Props) -> React.do
44+ style <- useStyles (pick props)
45+ theme ∷ CSSTheme <- useTheme
46+ let
47+ headerCluster =
48+ jsx cluster
49+ { space: "var(--s-5)"
50+ , align: baseline ∷ AlignItemsValue
51+ , justify: spaceBetween ∷ JustifyContentValue
52+ }
53+ [ R.div_
54+ [ classSpan style.name [ R.text spell.name ]
55+ , classSpan style.signature [ R.text spell.signature ]
56+ ]
57+ ]
58+ pure
59+ $ jsx card { divRef: props.cardRef }
60+ [ jsx box { className: style.container, padding: "var(--s-1)" }
61+ [ jsx stack { space: "var(--s-3)" }
62+ [ headerCluster
63+ , classSpan style.description [ R.text spell.description ]
64+ ]
65+ ]
66+ ]
components/src/Yoga/Grimoire/Spell/Spec.pursnew file+19
@@ -0,0 +1,19 @@
1+module Yoga.Grimoire.Spell.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.Grimoire.Spell.Component as Spell
9+import Yoga.Spec.Helpers (withSpecTheme)
10+
11+spec ∷ Spec Unit
12+spec =
13+ describeComponent (withSpecTheme Spell.makeComponent)
14+ "The Spell Component" do
15+ it "renders without problems" \spell -> do
16+ _ <-
17+ renderComponent spell
18+ $ justifill { spell: { description: "bla", name: "Heinz", signature: "Any -> Unit" } }
19+ pure unit
components/src/Yoga/Grimoire/Spell/Stories.pursnew file+20
@@ -0,0 +1,20 @@
1+module Yoga.Grimoire.Spell.Stories where
2+
3+import Prelude hiding (add)
4+import Effect (Effect)
5+import Justifill (justifill)
6+import React.Basic.DOM as R
7+import Storybook.Decorator.FullScreen (fullScreenDecorator)
8+import Storybook.React (Storybook, add, addDecorator, storiesOf)
9+import Yoga.Grimoire.Spell.Component as Spell
10+
11+stories ∷ Effect Storybook
12+stories = do
13+ storiesOf "Spell" do
14+ addDecorator fullScreenDecorator
15+ add "The Spell" Spell.makeComponent
16+ [ justifill
17+ { spell:
18+ { name: "append", signature: "a -> a -> a", description: "Takes two values and produces one" }
19+ }
20+ ]
components/src/Yoga/Grimoire/Spell/Styles.pursnew file+49
@@ -0,0 +1,49 @@
1+module Yoga.Grimoire.Spell.Styles where
2+
3+import Prelude hiding (top)
4+import CSS (ColorSpace(..), backgroundColor, border, borderRadius, color, fontFamily, fontSize, fontStyle, height, mix, pct, sansSerif, solid, width)
5+import CSS.FontStyle (italic)
6+import CSS.TextAlign (rightTextAlign, textAlign)
7+import Data.Array (fromFoldable)
8+import Data.NonEmpty (NonEmpty(..))
9+import Data.NonEmpty as NonEmpty
10+import JSS (JSSClasses, JSSElem, jss, jssClasses)
11+import Yoga.Theme.Types (YogaTheme)
12+
13+type PropsR
14+ = ()
15+
16+type Props
17+ = Record PropsR
18+
19+type Classes a
20+ = ( container ∷ a
21+ , signature ∷ a
22+ , description ∷ a
23+ , name ∷ a
24+ )
25+
26+styles ∷ JSSClasses YogaTheme Props (Classes (JSSElem Props))
27+styles =
28+ jssClasses \theme@{ s0, s1, s4, s5, s_5 } ->
29+ { container:
30+ jss { userSelect: "none" }
31+ <> jss do
32+ backgroundColor theme.backgroundColourLighter
33+ height (100.0 # pct)
34+ , signature:
35+ do
36+ color theme.textColour
37+ textAlign rightTextAlign
38+ fontFamily (fromFoldable theme.codeFontFamily) (NonEmpty.singleton sansSerif)
39+ fontStyle italic
40+ , name:
41+ do
42+ color theme.highlightColour
43+ fontFamily (fromFoldable theme.codeFontFamily) (NonEmpty.singleton sansSerif)
44+ fontSize s1
45+ , description:
46+ do
47+ color theme.grey
48+ fontStyle italic
49+ }
components/src/Yoga/Grimoire/Stories.purs+7−1
@@ -14,5 +14,11 @@ stories = do
14 addDecorator fullScreenDecorator
14 addDecorator fullScreenDecorator
15 add "The Grimoire" Grimoire.makeComponent
15 add "The Grimoire" Grimoire.makeComponent
16 [ justifill
16 [ justifill
17− {}
17+ { spells }
18 ]
18 ]
19+
20+spells =
21+ [ { name: "cast", signature: "String -> Effect Unit", description: "Casts an incantation" }
22+ , { name: "take", signature: "Int -> String -> String", description: "Takes the first characters of a string" }
23+ , { name: "append", signature: "a -> a -> a", description: "Takes two values and produces one" }
24+ ]
components/src/Yoga/Spell/Types.pursnew file+7
@@ -0,0 +1,7 @@
1+module Yoga.Spell.Types where
2+
3+type Spell
4+ = { name ∷ String
5+ , signature ∷ String
6+ , description ∷ String
7+ }