git.iko.soy/rowtype-yoga/ry-blocks
on main help sign in
A little less wrong
commit408d87d723210d9eb2de0664bb1d4b409beaa48a authorMark Eibes <mark.eibes@gmail.com> dateThu 10 Dec 2020, 22:48 (6 years ago) parente73cee7
23 files changed+511−387
package.json+2−2 src/React/Basic/SyntaxHighlighter/Story.purs−1 src/Yoga.purs+1−22 src/Yoga/Block/Atom/CodeInput/Story.purs+53−5 src/Yoga/Block/Atom/CodeInput/Style.purs+5−8 src/Yoga/Block/Atom/CodeInput/View.purs+24−27 src/Yoga/Block/Atom/Range/View.purs+5−3 src/Yoga/Block/Atom/Segmented/Story.purs+12−14 src/Yoga/Block/Atom/Segmented/View.purs+62−58 src/Yoga/Block/Container/View.purs+10−7 src/Yoga/Block/Internal.js+30−2 src/Yoga/Block/Internal.purs+71−24 src/Yoga/Block/Layout/Box/View.purs+5−2 src/Yoga/Block/Layout/Centre/View.purs+5−2 src/Yoga/Block/Layout/Cluster/View.purs+5−3 src/Yoga/Block/Layout/Imposter/View.purs+5−3 src/Yoga/Block/Layout/Sidebar/View.purs+5−3 src/Yoga/Block/Layout/Stack/View.purs+5−3 src/Yoga/Block/Modal/Story.purs+20−18 src/Yoga/Block/Modal/View.purs+51−49 src/Yoga/Block/Motion/Story.purs+121−125 src/Yoga/Prelude/View.purs+10−2 yarn.lock+4−4
package.json+2−2
@@ -18,7 +18,7 @@
1818 "source-map": "GerHobbelt/source-map#patch-8",
1919 "clean-webpack-plugin": "^3.0.0",
2020 "compression-webpack-plugin": "^6.0.3",
21− "framer-motion": "3.0.0-rc.22",
21+ "framer-motion": "^3.0.0",
2222 "html-webpack-plugin": "^4.5.0",
2323 "jsdom": "^16.3.0",
2424 "jsdom-global": "^3.0.2",
@@ -54,4 +54,4 @@
5454 "react-dom": "^16.0.0",
5555 "react-syntax-highlighter": "^15.3.1"
5656 }
57−}
57+}
src/React/Basic/SyntaxHighlighter/Story.purs−1
@@ -8,7 +8,6 @@ import React.Basic.DOM as R
88import React.Basic.Emotion as E
99import React.Basic.SyntaxHighlighter.Component (mkHighlighterTheme)
1010import React.Basic.SyntaxHighlighter.Component as SH
11−import Yoga (el)
1211import Yoga.Block.Container.Style as Styles
1312
1413default ∷
src/Yoga.purs+1−22
@@ -1,34 +1,13 @@
11module Yoga where
22
3−import Prelude
43import Data.Symbol (SProxy(..))
5−import Effect.Unsafe (unsafePerformEffect)
64import Prim.Row (class Lacks)
75import React.Basic.Emotion as Emotion
8−import React.Basic.Hooks (JSX, ReactChildren, ReactComponent, Render, reactChildrenFromArray)
6+import React.Basic.Hooks (JSX, ReactComponent)
97import React.Basic.Hooks as Hooks
108import Record as Record
119import Untagged.Coercible (class Coercible, coerce)
1210
13−reactComponent ∷
14− ∀ hooks props.
15− Lacks "children" props =>
16− Lacks "key" props =>
17− Lacks "ref" props =>
18− String ->
19− ({ | props } -> Render Unit hooks JSX) ->
20− ReactComponent { | props }
21−reactComponent = (map map map) unsafePerformEffect Hooks.reactComponent
22−
23−reactComponentWithChildren ∷
24− ∀ hooks props children.
25− Lacks "key" props =>
26− Lacks "ref" props =>
27− String ->
28− ({ children ∷ Hooks.ReactChildren children | props } -> Render Unit hooks JSX) ->
29− ReactComponent { children ∷ Hooks.ReactChildren children | props }
30−reactComponentWithChildren = (map map map) unsafePerformEffect Hooks.reactComponentWithChildren
31−
3211yogaElement ∷ ∀ allProps givenProps. Coercible givenProps (Record allProps) => ReactComponent (Record allProps) -> givenProps -> JSX
3312yogaElement el' props = Hooks.element el' (coerce props)
3413
src/Yoga/Block/Atom/CodeInput/Story.purs+53−5
@@ -1,13 +1,24 @@
11module Yoga.Block.Atom.CodeInput.Story where
22
33import Prelude
4−import Yoga.Block.Atom.CodeInput as CodeInput
5−import Yoga.Block.Container.Style as Styles
4+import Control.Monad.Maybe.Trans (lift, runMaybeT)
5+import Data.Foldable (traverse_)
6+import Data.Newtype (wrap)
7+import Data.Nullable as Nullable
8+import Data.Tuple.Nested ((/\))
69import Effect (Effect)
710import Effect.Unsafe (unsafePerformEffect)
8−import React.Basic (JSX, element, fragment)
11+import React.Basic (JSX, element, elementKeyed, fragment)
912import React.Basic.DOM as R
13+import React.Basic.DOM.Events (targetValue)
1014import React.Basic.Emotion as E
15+import React.Basic.Events (handler)
16+import React.Basic.Hooks (reactComponent)
17+import React.Basic.Hooks as React
18+import Web.HTML.HTMLElement (focus)
19+import Web.HTML.HTMLElement as HTMLElement
20+import Yoga.Block.Atom.CodeInput as CodeInput
21+import Yoga.Block.Container.Style as Styles
1122
1223default ∷
1324 { decorators ∷ Array (Effect JSX -> JSX)
@@ -25,11 +36,48 @@ default =
2536 }
2637
2738codeInput ∷ Effect JSX
28−codeInput =
39+codeInput = do
2940 pure
3041 $ fragment
31− [ element CodeInput.component
42+ [ R.h2_ [ R.text "No Options" ]
43+ , element CodeInput.component
3244 {}
3345 , element CodeInput.component
3446 { maxLength: 3 }
47+ , React.element refCompo {}
48+ , React.element controlled {}
3549 ]
50+ where
51+ refCompo =
52+ unsafePerformEffect
53+ $ reactComponent "Code Input Story" \{} -> React.do
54+ ref <- React.useRef Nullable.null
55+ React.useEffectAlways
56+ $ do
57+ _ <-
58+ runMaybeT do
59+ node <- React.readRefMaybe ref # wrap
60+ elem <- HTMLElement.fromNode node # pure # wrap
61+ focus elem # lift
62+ mempty
63+ pure
64+ $ fragment
65+ [ R.h2_ [ R.text "With Ref" ]
66+ , element CodeInput.component
67+ { ref
68+ }
69+ ]
70+
71+ controlled =
72+ unsafePerformEffect
73+ $ reactComponent "Code Input Controlled Story" \{} -> React.do
74+ text /\ setText <- React.useState' ""
75+ pure
76+ $ fragment
77+ [ R.h2_ [ R.text "Controlled" ]
78+ , elementKeyed CodeInput.component
79+ { value: text
80+ , onChange: handler targetValue (traverse_ setText)
81+ , key: "robinson-crusoe"
82+ }
83+ ]
src/Yoga/Block/Atom/CodeInput/Style.purs+5−8
@@ -1,20 +1,17 @@
11module Yoga.Block.Atom.CodeInput.Style where
22
33import Yoga.Prelude.Style
4−import Yoga.Block.Container.Style (colour)
54import Data.Interpolate (i)
6−import Untagged.Coercible (class Coercible, coerce)
5+import Untagged.Coercible (coerce)
6+import Yoga.Block.Container.Style (colour)
77
88type Props f r =
99 ( css ∷ f Style
10− , padding ∷ f StyleProperty
11− , borderWidth ∷ f String
12− , invert ∷ f Boolean
1310 | r
1411 )
1512
16−codeInput ∷ ∀ p c. Coercible c (OptionalProp Int) => { maxLength ∷ c | Props OptionalProp p } -> Style
17−codeInput props = styles <>? props.css
13+codeInput ∷ ∀ p. { maxLength ∷ Int | Props Id p } -> Style
14+codeInput props = styles <>? coerce props.css
1815 where
1916 styles =
2017 css
@@ -27,7 +24,7 @@ codeInput props = styles <>? props.css
2724 , fontFamily: str "var(--monoFont)"
2825 , fontSize: str "var(--s0)"
2926 , lineHeight: str "var(--s0)"
30− , width: str $ i "calc(" (coerce (props.maxLength) ?|| 10) "ch + 4.3 * var(--s-5))"
27+ , width: str $ i "calc(" (coerce props.maxLength ?|| 10) "ch + 4.3 * var(--s-5))"
3128 , padding: str "calc(var(--s-5) - 1px)"
3229 , color: str colour.text
3330 , "&:focus":
src/Yoga/Block/Atom/CodeInput/View.purs+24−27
@@ -1,38 +1,35 @@
1−module Yoga.Block.Atom.CodeInput.View (component, Props, PropsF) where
1+module Yoga.Block.Atom.CodeInput.View
2+ ( component
3+ , Props
4+ , EmotionProps
5+ ) where
26
37import Yoga.Prelude.View
8+import React.Basic.Emotion (Style)
49import Yoga.Block.Atom.CodeInput.Style as Style
5−import React.Basic.DOM as R
6−
7−type PropsF f =
8− ( className ∷ f String
9− | Style.Props f + InputProps
10− )
1110
1211type Props =
13− PropsF Id
12+ (
13+ | Style.Props Id (InputPropsF Id EmotionProps)
14+ )
1415
15−type PropsOptional =
16− PropsF OptionalProp
16+type EmotionProps =
17+ ( className ∷ String, css ∷ Style )
1718
1819component ∷ ∀ p q. Union p q Props => ReactComponent { | p }
19−component =
20+component = rawComponent
21+
22+rawComponent ∷ ∀ r. ReactComponent { | r }
23+rawComponent =
2024 mkForwardRefComponent "CodeInput" do
21− \(props ∷ { | PropsOptional }) ref -> React.do
25+ \(props ∷ { | Props }) ref -> React.do
2226 pure
23− $ styled R.div'
24− { className: "ry-inline-code-wrapper"
25− , css: Style.codeInputWrapper
27+ $ emotionInput ref
28+ props
29+ { className: "ry-inline-code"
30+ , css: Style.codeInput props
31+ , spellCheck: false
32+ , autoComplete: "false"
33+ , autoCorrect: "off"
34+ , autoCapitalize: "off"
2635 }
27− [ emotionInput
28− props
29− { className: "ry-inline-code " <>? props.className
30− , css: Style.codeInput props
31− , ref
32− , spellCheck: false
33− , onDragOver: handler preventDefault (const mempty)
34− , autoComplete: "false"
35− , autoCorrect: "off"
36− , autoCapitalize: "off"
37− }
38− ]
src/Yoga/Block/Atom/Range/View.purs+5−3
@@ -24,7 +24,10 @@ type PropsOptional =
2424 PropsF OptionalProp
2525
2626component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
27−component =
27+component = rawComponent
28+
29+rawComponent ∷ ∀ p. ReactComponent (Record p)
30+rawComponent =
2831 mkForwardRefComponent "Range" do
2932 \(props ∷ { | PropsOptional }) ref -> React.do
3033 let min = props.min ?|| 0
@@ -55,13 +58,12 @@ component =
5558 { className: "ry-range-focus-circle"
5659 , css: Style.focusCircle
5760 }
58− , emotionInput (props { max = show max, min = show min, value = show value })
61+ , emotionInput ref (props { max = show max, min = show min, value = show value })
5962 { className: "ry-range-thumb " <>? props.className
6063 , css: Style.range props <> guard props.disabled Style.inputDisabled <>? props.css
6164 , style: props.style
6265 , value: show value
6366 , type: "range"
6467 , onChange: handler Event.targetValue ((_ >>= Int.fromString) >>> (foldMap setValue))
65− , ref
6668 }
6769 ]
src/Yoga/Block/Atom/Segmented/Story.purs+12−14
@@ -1,17 +1,16 @@
11module Yoga.Block.Atom.Segmented.Story where
22
33import Prelude
4−import Yoga.Block.Container.Style as Styles
5−import Yoga.Block.Atom.Segmented as Segmented
64import Data.Tuple.Nested ((/\))
75import Effect (Effect)
86import Effect.Unsafe (unsafePerformEffect)
97import React.Basic (JSX, element)
108import React.Basic.DOM as R
119import React.Basic.Emotion as E
12−import React.Basic.Hooks (useState')
10+import React.Basic.Hooks (reactComponent, useState')
1311import React.Basic.Hooks as React
14−import Yoga (reactComponent)
12+import Yoga.Block.Atom.Segmented as Segmented
13+import Yoga.Block.Container.Style as Styles
1514
1615default ∷
1716 { decorators ∷ Array (Effect JSX -> JSX)
@@ -33,13 +32,12 @@ segmented = do
3332 demoComponent <- makeDemoComponent
3433 pure $ element demoComponent {}
3534 where
36− makeDemoComponent = do
37− pure
38− $ reactComponent "Segmented Demo" \{} -> React.do
39− activeIndex /\ setElementIndex <- useState' 0
40− pure
41− $ element Segmented.component
42− { activeIndex
43− , updateActiveIndex: setElementIndex
44− , buttonContents: R.text <$> [ "Heinz", "Dembi", "Merh", "mehr", "meeehr" ]
45− }
35+ makeDemoComponent =
36+ reactComponent "Segmented Demo" \{} -> React.do
37+ activeIndex /\ setElementIndex <- useState' 0
38+ pure
39+ $ element Segmented.component
40+ { activeIndex
41+ , updateActiveIndex: setElementIndex
42+ , buttonContents: R.text <$> [ "Heinz", "Dembi", "Merh", "mehr", "meeehr" ]
43+ }
src/Yoga/Block/Atom/Segmented/View.purs+62−58
@@ -1,28 +1,29 @@
11module Yoga.Block.Atom.Segmented.View (component, Props, MandatoryProps, PropsF, ComponentProps) where
22
33import Yoga.Prelude.View
4−import Yoga.Block.Layout.Cluster as Cluster
5−import Yoga.Block.Atom.Segmented.Style as Style
64import Control.Monad.Maybe.Trans (MaybeT(..), runMaybeT)
75import Control.Monad.Trans.Class (lift)
8−import Data.Array ((:))
96import Data.Array as A
107import Data.FoldableWithIndex (foldMapWithIndex)
11−import Data.Nullable (Nullable)
128import Data.Traversable (traverse)
9+import Effect.Aff (Milliseconds(..), delay)
10+import Effect.Unsafe (unsafePerformEffect)
1311import Foreign.Object as Object
1412import Framer.Motion (VariantLabel)
1513import Framer.Motion as Motion
16−import Hooks.UseResize (useResize')
14+import Hooks.UseResize (useResize)
1715import React.Basic.DOM (css)
1816import React.Basic.DOM as R
1917import React.Basic.Emotion as E
18+import React.Basic.Hooks (reactComponent)
2019import React.Basic.Hooks as React
20+import React.Basic.Hooks.Aff (useAff)
2121import Record.Extra (pick)
2222import Unsafe.Coerce (unsafeCoerce)
23−import Web.DOM (Node)
2423import Web.HTML.HTMLElement (getBoundingClientRect)
2524import Web.HTML.HTMLElement as HTMLElement
25+import Yoga.Block.Atom.Segmented.Style as Style
26+import Yoga.Block.Layout.Cluster as Cluster
2627
2728type PropsF f =
2829 (
@@ -40,21 +41,19 @@ type Props =
4041 PropsF Id
4142
4243activeComponent ∷ ∀ p p_. Union (MandatoryProps p) p_ Props => ReactComponent { | MandatoryProps p }
43−activeComponent =
44+activeComponent = rawActiveComponent
45+
46+rawActiveComponent ∷ ∀ p. ReactComponent { | p }
47+rawActiveComponent =
4448 mkForwardRefComponent "SegmentedActive" do
4549 \(props ∷ { | Props }) ref -> React.do
4650 maybeVariants /\ setVariants <- useState' Nothing
47− { active, previous } /\ setIndices <- useState' { active: props.activeItemIndex, previous: props.previousActiveItemIndex }
4851 let
4952 computeStyles = do
5053 maybeSt <- runMaybeT $ traverse getStyle props.activeItemRefs
5154 unless (maybeVariants == maybeSt) do
5255 for_ maybeSt (setVariants <<< Just)
53− void <<< useResize'
54− $ do
55− setIndices { active, previous: active }
56− computeStyles
57− useLayoutEffect props.activeItemIndex do
56+ useLayoutEffectAlways do
5857 computeStyles
5958 mempty
6059 let
@@ -64,20 +63,20 @@ activeComponent =
6463 styledLeaf Motion.div
6564 { css: Style.activeElement
6665 , className: "ry-active-segmented-element"
67− , initial: (unsafeCoerce <<< show) previous
66+ , initial: (unsafeCoerce <<< show) props.previousActiveItemIndex
6867 , transition: Motion.transition { type: "tween", duration: 0.2, ease: "easeOut" }
6968 , variants:
7069 Motion.variants $ maybeVariants
7170 # fromMaybe []
7271 # foldMapWithIndex (\i s -> Object.singleton (show i) (css s))
7372 # unsafeCoerce
74− , animate: Motion.animate ((unsafeCoerce $ show active) ∷ VariantLabel)
73+ , animate: Motion.animate ((unsafeCoerce <<< show $ props.activeItemIndex) ∷ VariantLabel)
7574 }
7675 children =
7776 [ E.element R.div'
7877 { className: "ry-segmented"
7978 , css: Style.segmented
80− , children: activeElement : props.children
79+ , children: A.cons activeElement props.children
8180 }
8281 ]
8382 pure
@@ -117,46 +116,51 @@ type ComponentProps =
117116
118117component ∷ ReactComponent ComponentProps
119118component =
120− reactComponent "Segmented" \({ buttonContents, activeIndex, updateActiveIndex } ∷ ComponentProps) -> React.do
121− previousActiveIndex /\ setPreviousActiveIndex <- useState' 0
122− initialised /\ initialise <- useState' false
123− itemRefs /\ setItemRefs <- useState' []
124− useEffect initialised do
125− refs <- traverse (const createRef) buttonContents
126− when (not initialised) do
127− initialise true
128− setItemRefs refs
129− pure (pure unit)
130− let
131− children ∷ Array JSX
132− children =
133− buttonContents `A.zip` itemRefs
134− # A.mapWithIndex \i (buttonContent /\ ref) -> do
135− let isLast = i + 1 == A.length buttonContents
136− let isFirst = i == 0
137− styled R.button'
138− { key: show i
139− , css: Style.button { isFirst, isLast }
140− , className: "ry-segmented-button"
141− , onClick:
142− handler preventDefault
143− $ const do
144− setPreviousActiveIndex activeIndex
145− updateActiveIndex i
146− , ref
147− }
148− [ buttonContent ]
149− pure
150− $ styled R.div'
151− { css: Style.wrapper
152− , className: "ry-segmented-wrapper"
153− }
154− [ styled activeComponent
155− { activeItemRefs: itemRefs
156− , activeItemIndex: activeIndex
157− , previousActiveItemIndex: previousActiveIndex
158− , css: Style.container
159− , className: "ry-segmented-container"
119+ unsafePerformEffect
120+ $ reactComponent "Segmented" \({ buttonContents, activeIndex, updateActiveIndex } ∷ ComponentProps) -> React.do
121+ previousActiveIndex /\ setPreviousActiveIndex <- useState' 0
122+ itemRefs /\ setItemRefs <- useState' []
123+ useLayoutEffectOnce do
124+ refs <- traverse (const createRef) buttonContents
125+ setItemRefs refs
126+ mempty
127+ windowSize <- useResize
128+ useAff windowSize do
129+ delay (100.0 # Milliseconds)
130+ liftEffect do -- force rerender
131+ refs <- traverse (const createRef) buttonContents
132+ setItemRefs refs
133+ let
134+ updateIndex idx = do
135+ setPreviousActiveIndex activeIndex
136+ updateActiveIndex idx
137+ children ∷ Array JSX
138+ children = A.mapWithIndex contentToChild refsAndContents
139+ refsAndContents ∷ Array (JSX /\ Ref (Nullable Node))
140+ refsAndContents = A.zip buttonContents itemRefs
141+ contentToChild ∷ Int -> (JSX /\ Ref (Nullable Node)) -> JSX
142+ contentToChild idx (buttonContent /\ ref) = do
143+ let isLast = idx + 1 == A.length buttonContents
144+ let isFirst = idx == 0
145+ styled R.button'
146+ { key: show idx
147+ , ref
148+ , css: Style.button { isFirst, isLast }
149+ , className: "ry-segmented-button"
150+ , onClick: handler preventDefault (const (updateIndex idx))
160151 }
161− children
162− ]
152+ [ buttonContent ]
153+ pure
154+ $ styled R.div'
155+ { css: Style.wrapper
156+ , className: "ry-segmented-wrapper"
157+ }
158+ [ styled activeComponent
159+ { activeItemRefs: itemRefs
160+ , activeItemIndex: activeIndex
161+ , previousActiveItemIndex: previousActiveIndex
162+ , css: Style.container
163+ , className: "ry-segmented-container"
164+ }
165+ children
166+ ]
src/Yoga/Block/Container/View.purs+10−7
@@ -1,19 +1,22 @@
11module Yoga.Block.Container.View (component, Props) where
22
33import Yoga.Prelude.View
4−import Yoga.Block.Container.Style as Styles
54import Data.Array as Array
5+import Effect.Unsafe (unsafePerformEffect)
66import React.Basic.DOM as R
77import React.Basic.Emotion as E
8+import React.Basic.Hooks (reactComponentWithChildren)
9+import Yoga.Block.Container.Style as Styles
810
911type Props =
1012 { children ∷ ReactChildren JSX }
1113
1214component ∷ ReactComponent Props
1315component =
14− reactComponentWithChildren "Container" \({ children } ∷ Props) -> React.do
15− pure
16− $ R.div_
17− $ Array.cons
18− (element E.global { styles: Styles.global })
19− (reactChildrenToArray children)
16+ unsafePerformEffect
17+ $ reactComponentWithChildren "Container" \({ children } ∷ Props) -> React.do
18+ pure
19+ $ R.div_
20+ $ Array.cons
21+ (element E.global { styles: Styles.global })
22+ (reactChildrenToArray children)
src/Yoga/Block/Internal.js+30−2
@@ -3,6 +3,7 @@ const React = require("react")
33exports.mkForwardRefComponent = (displayName) => (renderFn) => {
44 const component = (props, ref) => renderFn(props)(ref)();
55 component.displayName = displayName;
6+ component.whyDidYouRender = true;
67 return React.forwardRef(component);
78};
89
@@ -13,14 +14,41 @@ exports.mkForwardRefComponentEffect = (displayName) => (renderFn) => () => {
1314 return React.forwardRef(component);
1415};
1516
16−exports.pickDefinedFn = function (ks, obj) {
17− const copy = {};
17+exports.pickDefinedFn = function (ref, ks, obj) {
18+ const copy = {}
1819 for (let i = 0; i < ks.length; i++) {
1920 if (obj[ks[i]] !== undefined) {
2021 copy[ks[i]] = obj[ks[i]];
2122 }
2223 }
24+ if (ref !== undefined) {
25+ copy.ref = ref
26+ }
2327 return copy;
2428};
2529
2630exports.createRef = React.createRef
31+
32+exports.unsafeMergeSecond = (r1) => (r2) => {
33+ for (var k1 in r2) {
34+ if ({}.hasOwnProperty.call(r2, k1) && r2[k1] !== undefined) {
35+ r1[k1] = r2[k1];
36+ }
37+ }
38+ return r1
39+}
40+
41+exports.unsafeUnionDroppingUndefined = (r1) => (r2) => {
42+ var copy = {};
43+ for (var k1 in r2) {
44+ if ({}.hasOwnProperty.call(r2, k1) && r2[k1] !== undefined) {
45+ copy[k1] = r2[k1];
46+ }
47+ }
48+ for (var k2 in r1) {
49+ if ({}.hasOwnProperty.call(r1, k2) && r1[k2] !== undefined) {
50+ copy[k2] = r1[k2];
51+ }
52+ }
53+ return copy;
54+}
src/Yoga/Block/Internal.purs+71−24
@@ -9,22 +9,22 @@ module Yoga.Block.Internal
99 , InputProps
1010 , InputPropsF
1111 , emotionDiv
12− , emotionDiv_
1312 , emotionInput
1413 , module Yoga.Block.Internal.OptionalProp
1514 , module Yoga.Block.Internal.CSS
15+ , unsafeUnionDroppingUndefined
16+ , unsafeMergeSecond
1617 , createRef
1718 ) where
1819
1920import Prelude
20−import Yoga.Block.Internal.OptionalProp (Id, OptionalProp(..), appendIfDefined, getOr, getOrFlipped, ifTrue, isTruthy, maybeToOp, opToMaybe, unsafeUnOptional, (<>?), (?||))
21−import Data.Array (fromFoldable)
22−import Data.Function.Uncurried (Fn2, runFn2)
21+import Data.Array as Array
22+import Data.Function.Uncurried (Fn3, runFn3)
2323import Data.Nullable (Nullable)
2424import Effect (Effect)
2525import Effect.Unsafe (unsafePerformEffect)
2626import Foreign.Object (Object)
27−import Prim.Row (class Union)
27+import Prim.Row (class Lacks, class Union)
2828import Prim.Row as Row
2929import Prim.RowList as RL
3030import React.Basic.DOM (CSS, unsafeCreateDOMComponent)
@@ -33,10 +33,10 @@ import React.Basic.Emotion as E
3333import React.Basic.Events (EventHandler)
3434import React.Basic.Hooks (JSX, ReactComponent, Ref, Render)
3535import Record.Extra (class Keys, keys)
36−import Record.Unsafe.Union (unsafeUnion)
3736import Type.Data.Row (RProxy(..))
3837import Web.DOM (Node)
3938import Yoga.Block.Internal.CSS (_0)
39+import Yoga.Block.Internal.OptionalProp (Id, OptionalProp(..), appendIfDefined, getOr, getOrFlipped, ifTrue, isTruthy, maybeToOp, opToMaybe, unsafeUnOptional, (<>?), (?||))
4040
4141foreign import mkForwardRefComponent ∷
4242 ∀ inputProps props a hooks.
@@ -52,52 +52,97 @@ foreign import mkForwardRefComponentEffect ∷
5252
5353foreign import createRef ∷ ∀ a. Effect (Ref a)
5454
55−unsafeEmotion ∷ ∀ props propsA propsB ref. ReactComponent { className ∷ String, css ∷ E.Style, ref ∷ Ref ref | props } -> Record propsA -> { className ∷ String, css ∷ E.Style, ref ∷ Ref ref | propsB } -> JSX
56−unsafeEmotion component propsA propsB = E.element component (unsafeUnion propsB propsA)
55+foreign import unsafeUnionDroppingUndefined ∷ ∀ r1 r2 r3. Record r1 -> Record r2 -> Record r3
56+
57+foreign import unsafeMergeSecond ∷ ∀ r1 r2 r3. Record r1 -> Record r2 -> Record r3
58+
59+unsafeEmotion ∷ ∀ props propsA propsB. ReactComponent { className ∷ String, css ∷ E.Style | props } -> Record propsA -> { className ∷ String, css ∷ E.Style | propsB } -> JSX
60+unsafeEmotion component propsA propsB = E.element component (unsafeUnionDroppingUndefined propsB propsA)
61+
62+unsafeEmotionKeyed ∷ ∀ props propsA propsB. ReactComponent { className ∷ String, css ∷ E.Style, key ∷ String | props } -> Record propsA -> { className ∷ String, css ∷ E.Style | propsB } -> JSX
63+unsafeEmotionKeyed component propsA propsB = E.elementKeyed component (unsafeUnionDroppingUndefined propsB propsA)
5764
5865emotionDiv_ ∷
5966 ∀ props props_.
67+ Lacks "ref" props =>
6068 Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | DivProps ) =>
6169 (Record (DivProps)) ->
6270 { className ∷ String
6371 , css ∷ Style
64− , ref ∷ Ref (Nullable Node)
6572 | props
6673 } ->
6774 JSX
6875emotionDiv_ = unsafeEmotion unsafeDiv
6976
70−emotionDiv = emotionDiv_ <<< pickDefined
77+emotionDiv ∷
78+ ∀ props props_ more.
79+ Lacks "ref" props =>
80+ Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | DivProps ) =>
81+ Ref (Nullable Node) ->
82+ { | DivPropsF Id more } ->
83+ { className ∷ String
84+ , css ∷ Style
85+ | props
86+ } ->
87+ JSX
88+emotionDiv ref = emotionDiv_ <<< pickDefined ref
7189
72−foreign import pickDefinedFn ∷ ∀ r1 r2. Fn2 (Array String) (Record r1) (Record r2)
90+unsafeDiv ∷ ∀ r. ReactComponent (Record r)
91+unsafeDiv = dangerous "div"
92+
93+foreign import pickDefinedFn ∷ ∀ r1 r2. Fn3 (Ref (Nullable Node)) (Array String) (Record r1) (Record r2)
7394
7495pickDefined ∷
7596 ∀ a r b l.
7697 Row.Union b r a =>
7798 RL.RowToList b l =>
99+ Ref (Nullable Node) ->
78100 Keys l =>
79101 Record a ->
80− Record b
81−pickDefined = runFn2 pickDefinedFn ks
102+ { ref ∷ Ref (Nullable Node) | b }
103+pickDefined ref = runFn3 pickDefinedFn ref ks
82104 where
83− ks = fromFoldable $ keys (RProxy ∷ RProxy b)
84−
85−unsafeDiv = dangerous "div"
105+ ks = Array.fromFoldable $ keys (RProxy ∷ RProxy b)
86106
87107emotionInput_ ∷
88108 ∀ props props_.
109+ Lacks "ref" props =>
89110 Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | InputProps ) =>
90− (Record (InputProps)) ->
111+ { | InputProps } ->
91112 { className ∷ String
92113 , css ∷ Style
93− , ref ∷ Ref (Nullable Node)
94114 | props
95115 } ->
96116 JSX
97117emotionInput_ = unsafeEmotion unsafeInput
98118
99−emotionInput = emotionInput_ <<< pickDefined
119+emotionInputKeyed_ ∷
120+ ∀ props props_.
121+ Lacks "ref" props =>
122+ Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node), key ∷ String | InputProps ) =>
123+ { | InputProps } ->
124+ { className ∷ String
125+ , css ∷ Style
126+ , key ∷ String
127+ | props
128+ } ->
129+ JSX
130+emotionInputKeyed_ = unsafeEmotionKeyed unsafeInput
100131
132+emotionInput ∷
133+ ∀ props props_ more.
134+ Lacks "ref" props =>
135+ Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | InputProps ) =>
136+ Ref (Nullable Node) ->
137+ { | InputPropsF Id more } ->
138+ { className ∷ String
139+ , css ∷ Style
140+ | props
141+ } ->
142+ JSX
143+emotionInput ref = emotionInput_ <<< pickDefined ref
144+
145+unsafeInput ∷ ∀ r. ReactComponent (Record r)
101146unsafeInput = dangerous "input"
102147
103148dangerous ∷ ∀ props. String -> ReactComponent (Record props)
@@ -106,9 +151,9 @@ dangerous = unsafePerformEffect <<< unsafeCreateDOMComponent
106151-- type DivProps =
107152-- Props_div
108153type DivProps =
109− DivPropsF Id
154+ DivPropsF Id ()
110155
111−type DivPropsF f =
156+type DivPropsF f more =
112157 ( _aria ∷ f (Object String)
113158 , _data ∷ f (Object String)
114159 , about ∷ f String
@@ -238,12 +283,13 @@ type DivPropsF f =
238283 , useMap ∷ f String
239284 , vocab ∷ f String
240285 , wmode ∷ f String
286+ | more
241287 )
242288
243289type InputProps =
244− InputPropsF Id
290+ InputPropsF Id ()
245291
246−type InputPropsF f =
292+type InputPropsF f more =
247293 ( _aria ∷ f (Object String)
248294 , _data ∷ f (Object String)
249295 , about ∷ f String
@@ -369,8 +415,8 @@ type InputPropsF f =
369415 , prefix ∷ f String
370416 , property ∷ f String
371417 , radioGroup ∷ f String
372− , readOnly ∷ f Boolean
373418 , ref ∷ f (Ref (Nullable Node))
419+ , readOnly ∷ f Boolean
374420 , required ∷ f Boolean
375421 , resource ∷ f String
376422 , results ∷ f String
@@ -401,4 +447,5 @@ type InputPropsF f =
401447 , wmode ∷ f String
402448 , min ∷ f (String)
403449 , max ∷ f (String)
450+ | more
404451 )
src/Yoga/Block/Layout/Box/View.purs+5−2
@@ -15,13 +15,16 @@ type PropsOptional =
1515 PropsF OptionalProp
1616
1717component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
18−component =
18+component = rawComponent
19+
20+rawComponent ∷ ∀ p. ReactComponent { | p }
21+rawComponent =
1922 mkForwardRefComponent "Box" do
2023 \(props ∷ { | PropsOptional }) ref -> React.do
2124 pure
2225 $ emotionDiv
26+ ref
2327 props
2428 { className: "ry-box " <>? props.className
2529 , css: Style.box props
26− , ref
2730 }
src/Yoga/Block/Layout/Centre/View.purs+5−2
@@ -15,13 +15,16 @@ type PropsOptional =
1515 PropsF OptionalProp
1616
1717component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
18−component =
18+component = rawComponent
19+
20+rawComponent ∷ ∀ p. ReactComponent { | p }
21+rawComponent =
1922 mkForwardRefComponent "Centre" do
2023 \(props ∷ { | PropsOptional }) ref -> React.do
2124 pure
2225 $ emotionDiv
26+ ref
2327 props
2428 { className: "ry-centre " <>? props.className
2529 , css: Style.centre props
26− , ref
2730 }
src/Yoga/Block/Layout/Cluster/View.purs+5−3
@@ -15,12 +15,14 @@ type PropsOptional =
1515 PropsF OptionalProp
1616
1717component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
18−component =
18+component = rawComponent
19+
20+rawComponent ∷ ∀ p. ReactComponent { | p }
21+rawComponent =
1922 mkForwardRefComponent "Cluster" do
2023 \(props ∷ { | PropsOptional }) ref -> React.do
2124 pure
22− $ emotionDiv props
25+ $ emotionDiv ref props
2326 { className: "ry-cluster " <>? props.className
2427 , css: Style.cluster props
25− , ref
2628 }
src/Yoga/Block/Layout/Imposter/View.purs+5−3
@@ -15,12 +15,14 @@ type PropsOptional =
1515 PropsF OptionalProp
1616
1717component ∷ ∀ p q. Union p q Props => ReactComponent { | p }
18−component = do
18+component = rawComponent
19+
20+rawComponent ∷ ∀ p. ReactComponent { | p }
21+rawComponent =
1922 mkForwardRefComponent "Imposter" do
2023 \(props ∷ { | PropsOptional }) ref -> React.do
2124 pure
22− $ emotionDiv props
25+ $ emotionDiv ref props
2326 { className: "ry-imposter " <>? props.className
2427 , css: Style.imposter props
25− , ref
2628 }
src/Yoga/Block/Layout/Sidebar/View.purs+5−3
@@ -15,12 +15,14 @@ type PropsOptional =
1515 PropsF OptionalProp
1616
1717component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
18−component =
18+component = rawComponent
19+
20+rawComponent ∷ ∀ p. ReactComponent { | p }
21+rawComponent =
1922 mkForwardRefComponent "Sidebar" do
2023 \(props ∷ { | PropsOptional }) ref -> React.do
2124 pure
22− $ emotionDiv props
25+ $ emotionDiv ref props
2326 { className: "ry-sidebar " <>? props.className
2427 , css: Style.sidebar props
25− , ref
2628 }
src/Yoga/Block/Layout/Stack/View.purs+5−3
@@ -15,12 +15,14 @@ type PropsOptional =
1515 PropsF OptionalProp
1616
1717component ∷ ∀ p q. Union p q Props => ReactComponent { | p }
18−component =
18+component = rawComponent
19+
20+rawComponent ∷ ∀ p. ReactComponent { | p }
21+rawComponent =
1922 mkForwardRefComponent "Stack" do
2023 \(props ∷ { | PropsOptional }) ref -> React.do
2124 pure
22− $ emotionDiv props
25+ $ emotionDiv ref props
2326 { className: "ry-stack " <>? props.className
2427 , css: Style.stack props
25− , ref
2628 }
src/Yoga/Block/Modal/Story.purs+20−18
@@ -1,8 +1,6 @@
11module Yoga.Block.Modal.Story where
22
33import Prelude
4−import Yoga.Block.Container.Style as Styles
5−import Yoga.Block.Modal as Modal
64import Data.Tuple.Nested ((/\))
75import Effect (Effect)
86import Effect.Unsafe (unsafePerformEffect)
@@ -10,9 +8,12 @@ import React.Basic (JSX, element, fragment)
108import React.Basic.DOM as R
119import React.Basic.Emotion as E
1210import React.Basic.Events (handler_)
11+import React.Basic.Hooks (reactComponent)
1312import React.Basic.Hooks as React
1413import Yoga as Y
1514import Yoga.Block as Block
15+import Yoga.Block.Container.Style as Styles
16+import Yoga.Block.Modal as Modal
1617
1718default ∷
1819 { decorators ∷ Array (Effect JSX -> JSX)
@@ -34,20 +35,21 @@ modal = do
3435 pure $ React.element compo {}
3536 where
3637 compo =
37− Y.reactComponent "Modal Story" \{} -> React.do
38− isOpen /\ setIsOpen <- React.useState' true
39− pure
40− $ fragment
41− [ R.h2_ [ R.text "No Options" ]
42− , Y.el R.button'
43− { onClick: handler_ (setIsOpen true)
44− }
45− [ R.text "Show Modal"
38+ unsafePerformEffect
39+ $ reactComponent "Modal Story" \{} -> React.do
40+ isOpen /\ setIsOpen <- React.useState' true
41+ pure
42+ $ fragment
43+ [ R.h2_ [ R.text "No Options" ]
44+ , Y.el R.button'
45+ { onClick: handler_ (setIsOpen true)
46+ }
47+ [ R.text "Show Modal"
48+ ]
49+ , element Modal.component
50+ { content:
51+ Y.el Block.box {} [ R.text "hi" ]
52+ , isOpen
53+ , setIsOpen
54+ }
4655 ]
47− , element Modal.component
48− { content:
49− Y.el Block.box {} [ R.text "hi" ]
50− , isOpen
51− , setIsOpen
52− }
53− ]
src/Yoga/Block/Modal/View.purs+51−49
@@ -1,17 +1,16 @@
11module Yoga.Block.Modal.View (component, Props) where
22
33import Yoga.Prelude.View
4−import Yoga.Block.Layout.Imposter as Imposter
5−import Yoga.Block.Modal.Style as Style
6−import Data.Nullable (Nullable)
74import Data.Nullable as Nullable
85import Effect.Unsafe (unsafePerformEffect)
96import Framer.Motion (withMotion)
107import Framer.Motion as Motion
118import React.Basic.DOM (css)
129import React.Basic.Emotion as Emotion
10+import React.Basic.Hooks (reactComponent)
1311import React.Basic.Hooks as React
14−import Web.DOM (Node)
12+import Yoga.Block.Layout.Imposter as Imposter
13+import Yoga.Block.Modal.Style as Style
1514
1615type Props =
1716 { content ∷ JSX
@@ -22,58 +21,61 @@ type Props =
2221
2322component ∷ ReactComponent Props
2423component =
25− reactComponent "Modal Wrapper" \{ content, isOpen, setIsOpen } -> React.do
26− clickAwayRef <- React.useRef Nullable.null
27− pure
28− $ fragment
29− [ el Motion.animatePresence {}
30− $ guard isOpen
31− [ element clickaway { theRef: clickAwayRef, hide: setIsOpen false }
24+ unsafePerformEffect
25+ $ reactComponent "Modal Wrapper" \{ content, isOpen, setIsOpen } -> React.do
26+ clickAwayRef <- React.useRef Nullable.null
27+ pure
28+ $ fragment
29+ [ el Motion.animatePresence {}
30+ $ guard isOpen
31+ [ element clickaway { theRef: clickAwayRef, hide: setIsOpen false }
32+ ]
33+ , el Motion.animatePresence {}
34+ [ guard isOpen
35+ $ element window { clickAwayRef, hide: setIsOpen false, content }
3236 ]
33− , el Motion.animatePresence {}
34− [ guard isOpen
35− $ element window { clickAwayRef, hide: setIsOpen false, content }
3637 ]
37− ]
3838
3939clickaway ∷ ReactComponent { theRef ∷ Ref (Nullable Node), hide ∷ Effect Unit }
4040clickaway =
41− reactComponent "Modal Clickaway" \{ theRef, hide } -> React.do
42− pure $ Emotion.elementKeyed Motion.div
43− $ { key: "ry-modal-clickaway"
44− , onClick: handler_ hide
45− , className: "ry-modal-clickaway"
46− , css: Style.clickaway
47− , initial: Motion.prop $ css { opacity: 0.0 }
48− , animate: Motion.prop $ css { opacity: 1.0 }
49− , exit: Motion.prop $ css { opacity: 0.0 }
50− , ref: theRef
51− }
41+ unsafePerformEffect
42+ $ reactComponent "Modal Clickaway" \{ theRef, hide } -> React.do
43+ pure $ Emotion.elementKeyed Motion.div
44+ $ { key: "ry-modal-clickaway"
45+ , onClick: handler_ hide
46+ , className: "ry-modal-clickaway"
47+ , css: Style.clickaway
48+ , initial: Motion.prop $ css { opacity: 0.0 }
49+ , animate: Motion.prop $ css { opacity: 1.0 }
50+ , exit: Motion.prop $ css { opacity: 0.0 }
51+ , ref: theRef
52+ }
5253
53−window ∷ ReactComponent { clickAwayRef ∷ Ref (Nullable Node), content ∷ JSX, hide ∷ Effect Unit }
54+window ∷ ReactComponent { clickAwayRef ∷ NodeRef, content ∷ JSX, hide ∷ Effect Unit }
5455window =
55− reactComponent "Modal Window" \{ clickAwayRef, content, hide } -> React.do
56− pure
57− $ Emotion.elementKeyed motionImposter
58− ( { className: "ry-modal-window"
59− , css: Style.modal
60− , key: "ry-modal-window"
61− , children:
62− [ styled Motion.div
63− { className: "ry-modal"
64− , css: Style.modal
65− , drag: Motion.prop true
66− , dragMomentum: Motion.prop false
67− , dragConstraints: Motion.prop clickAwayRef
68− }
69− [ content ]
70− ]
71− }
72− `withMotion`
73− { initial: css { transform: "translate(-50%, -50%) scale3d(0.1,0.1,0.1)", opacity: 0 }
74− , animate: css { transform: "translate(-50%, -50%) scale3d(1,1,1)", opacity: 1 }
75− , exit: css { transform: "translate(-50%, -50%) scale3d(0.1,0.1,0.1)", opacity: 0 }
56+ unsafePerformEffect
57+ $ reactComponent "Modal Window" \{ clickAwayRef, content, hide } -> React.do
58+ pure
59+ $ Emotion.elementKeyed motionImposter
60+ ( { className: "ry-modal-window"
61+ , css: Style.modal
62+ , key: "ry-modal-window"
63+ , children:
64+ [ styled Motion.div
65+ { className: "ry-modal"
66+ , css: Style.modal
67+ , drag: Motion.prop true
68+ , dragMomentum: Motion.prop false
69+ , dragConstraints: Motion.prop clickAwayRef
70+ }
71+ [ content ]
72+ ]
7673 }
77− )
74+ `withMotion`
75+ { initial: css { transform: "translate(-50%, -50%) scale3d(0.1,0.1,0.1)", opacity: 0 }
76+ , animate: css { transform: "translate(-50%, -50%) scale3d(1,1,1)", opacity: 1 }
77+ , exit: css { transform: "translate(-50%, -50%) scale3d(0.1,0.1,0.1)", opacity: 0 }
78+ }
79+ )
7880 where
7981 motionImposter = unsafePerformEffect $ Motion.custom Imposter.component
src/Yoga/Block/Motion/Story.purs+121−125
@@ -1,10 +1,6 @@
11module Yoga.Block.Motion.Story where
22
33import Prelude
4−import Yoga.Block.Layout.Centre as Centre
5−import Yoga.Block.Container.Style as Styles
6−import Yoga.Block.Layout.Sidebar as Sidebar
7−import Yoga.Block.Layout.Stack as Stack
84import Data.Monoid (guard)
95import Data.Tuple (Tuple(..))
106import Data.Tuple.Nested ((/\))
@@ -18,12 +14,16 @@ import React.Basic.DOM as R
1814import React.Basic.Emotion (center, flex)
1915import React.Basic.Emotion as E
2016import React.Basic.Events (handler_)
21−import React.Basic.Hooks (useState)
17+import React.Basic.Hooks (reactComponent, useState)
2218import React.Basic.Hooks as React
2319import Untagged.Coercible (coerce)
24−import Yoga (el, reactComponent, styled)
20+import Yoga (el, styled)
21+import Yoga.Block.Container.Style as Styles
2522import Yoga.Block.Internal (_0)
2623import Yoga.Block.Internal.CSS (_100percent)
24+import Yoga.Block.Layout.Centre as Centre
25+import Yoga.Block.Layout.Sidebar as Sidebar
26+import Yoga.Block.Layout.Stack as Stack
2727
2828default ∷
2929 { decorators ∷ Array (Effect JSX -> JSX)
@@ -47,29 +47,27 @@ motion = do
4747 where
4848 mkMc = do
4949 motionCentre <- M.custom Centre.component
50− pure
51− $ reactComponent "MotionTest" \{} -> React.do
52− Tuple isOpen setIsOpen <- React.useState false
53− pure
54− $ fragment
55− [ E.element R.div'
56− { className: "bg"
57− , css: backgroundStyle
58− , children:
59− [ E.element motionCentre
60− ( { className: "parent"
61− , css: parentStyle <> if isOpen then parentStyleOpen else mempty
62− , onClick: handler_ (setIsOpen not)
63− , style: css { y: if isOpen then -70 else 0, skew: if isOpen then 30 else 0 }
50+ reactComponent "MotionTest" \{} -> React.do
51+ Tuple isOpen setIsOpen <- React.useState false
52+ pure
53+ $ fragment
54+ [ E.element R.div'
55+ { className: "bg"
56+ , css: backgroundStyle
57+ , children:
58+ [ E.element motionCentre
59+ ( { className: "parent"
60+ , css: parentStyle <> if isOpen then parentStyleOpen else mempty
61+ , onClick: handler_ (setIsOpen not)
62+ }
63+ `withMotion`
64+ { layout: true
65+ , initial: css { borderRadius: 50, y: 0 }
6466 }
65− `withMotion`
66− { layout: true
67− , initial: css { borderRadius: 50 }
68− }
69− )
70− ]
71− }
72− ]
67+ )
68+ ]
69+ }
70+ ]
7371
7472 backgroundStyle ∷ E.Style
7573 backgroundStyle =
@@ -121,120 +119,118 @@ layoutTrans = do
121119 mc <- mkMc
122120 pure $ element mc {}
123121 where
124− mkMc = do
125− pure
126− $ reactComponent "MotionTest" \{} -> React.do
127− sidebarOpen /\ setSidebarOpen <- useState true
128− let
129− ava1 =
130− el M.div
131− { layout: coerce true
132− , layoutId: coerce "ava"
133− , key: "ava"
134− , onClick: handler_ (setSidebarOpen not)
135− , transition: M.transition { delay: 0.2, type: "spring", damping: 30, stiffness: 200 }
136− , style:
137− css
138− { height: "200px"
139− , width: "200px"
140− , borderRadius: "50%"
141− , border: "4px solid darkslateblue"
142− , backgroundImage: "url('https://pbs.twimg.com/profile_images/1166763324723404801/nAUqF6tX.jpg')"
143− , backgroundSize: "cover"
144− }
122+ mkMc =
123+ reactComponent "MotionTest" \{} -> React.do
124+ sidebarOpen /\ setSidebarOpen <- useState true
125+ let
126+ ava1 =
127+ el M.div
128+ { layout: coerce true
129+ , layoutId: coerce "ava"
130+ , key: "ava"
131+ , onClick: handler_ (setSidebarOpen not)
132+ , transition: M.transition { delay: 0.2, type: "spring", damping: 30, stiffness: 200 }
133+ , style:
134+ css
135+ { height: "200px"
136+ , width: "200px"
137+ , borderRadius: "50%"
138+ , border: "4px solid darkslateblue"
139+ , backgroundImage: "url('https://pbs.twimg.com/profile_images/1166763324723404801/nAUqF6tX.jpg')"
140+ , backgroundSize: "cover"
145141 }
146− []
147− ava2 =
148− el M.div
149− { layout: coerce true
150− , layoutId: coerce "ava"
151− , key: "ava"
152− , onClick: handler_ (setSidebarOpen not)
153− , style:
154− css
155− { height: "100px"
156− , width: "100px"
157− , backgroundImage: "url('https://pbs.twimg.com/profile_images/1166763324723404801/nAUqF6tX.jpg')"
158− , backgroundSize: "cover"
159− , borderRadius: "50%"
160− , border: "2px solid darkslateblue"
161− }
142+ }
143+ []
144+ ava2 =
145+ el M.div
146+ { layout: coerce true
147+ , layoutId: coerce "ava"
148+ , key: "ava"
149+ , onClick: handler_ (setSidebarOpen not)
150+ , style:
151+ css
152+ { height: "100px"
153+ , width: "100px"
154+ , backgroundImage: "url('https://pbs.twimg.com/profile_images/1166763324723404801/nAUqF6tX.jpg')"
155+ , backgroundSize: "cover"
156+ , borderRadius: "50%"
157+ , border: "2px solid darkslateblue"
162158 }
163− []
164− ava3 =
165− el M.div
166− { onClick: handler_ (setSidebarOpen not)
167− , exit: M.exit (css { scale: 1.4, opacity: 0 })
168− , transition: M.transition { duration: 0.19 }
169− , style:
170− css
171− { height: "100px"
172− , width: "100px"
173− , background: "oldlace"
174− , borderRadius: "50%"
175− , border: "4px solid darkslateblue"
176− }
159+ }
160+ []
161+ ava3 =
162+ el M.div
163+ { onClick: handler_ (setSidebarOpen not)
164+ , exit: M.exit (css { scale: 1.4, opacity: 0 })
165+ , transition: M.transition { duration: 0.19 }
166+ , style:
167+ css
168+ { height: "100px"
169+ , width: "100px"
170+ , background: "oldlace"
171+ , borderRadius: "50%"
172+ , border: "4px solid darkslateblue"
177173 }
178− []
179− pure
180− $ el animateSharedLayout {}
181− [ el M.animatePresence {}
182− [ if sidebarOpen then
183− ava1
184− else
185− el Stack.component {} [ ava2, ava3 ]
186− ]
174+ }
175+ []
176+ pure
177+ $ el animateSharedLayout {}
178+ [ el M.animatePresence {}
179+ [ if sidebarOpen then
180+ ava1
181+ else
182+ el Stack.component {} [ ava2, ava3 ]
187183 ]
184+ ]
188185
189186animatedSidebar ∷ Effect JSX
190187animatedSidebar = do
191188 mc <- mkMc
192189 pure $ element mc {}
193190 where
194− mkMc = do
195− pure
196− $ reactComponent "MotionTest" \{} -> React.do
197− sidebarOpen /\ setSidebarOpen <- useState true
198− let
199− sb =
200− styled M.div
201− { className: "sidebar"
202− , css: if sidebarOpen then sidebarStyleOpen else sidebarStyleHidden
203− , onClick: handler_ (setSidebarOpen not)
204− , initial: M.initial $ css { opacity: 0 }
205− , animate: M.animate $ css { opacity: 1, width: "200px" }
206− , exit: M.exit $ css { opacity: 0 }
207− , key: "sidebar"
208− }
209− [ R.text $ if sidebarOpen then "Sidebar" else "|||" ]
210− pure
211− $ styled R.div'
212− { className: "bg"
213− , css: backgroundStyle
191+ mkMc =
192+ reactComponent "MotionTest" \{} -> React.do
193+ sidebarOpen /\ setSidebarOpen <- useState true
194+ let
195+ sb =
196+ styled M.div
197+ { className: "sidebar"
198+ , css: if sidebarOpen then sidebarStyleOpen else sidebarStyleHidden
199+ , onClick: handler_ (setSidebarOpen not)
200+ , initial: M.initial $ css { opacity: 0 }
201+ , animate: M.animate $ css { opacity: 1, width: "200px" }
202+ , exit: M.exit $ css { opacity: 0 }
203+ , key: "sidebar"
204+ }
205+ [ R.text $ if sidebarOpen then "Sidebar" else "|||" ]
206+ pure
207+ $ styled R.div'
208+ { className: "bg"
209+ , css: backgroundStyle
210+ }
211+ [ el Sidebar.component
212+ { className: "parent"
213+ , css: sidebarContainerStyle
214214 }
215− [ el Sidebar.component
216− { className: "parent"
217− , css: sidebarContainerStyle
215+ [ styled R.div'
216+ { css: sidebarStyle
217+ , className: "sidebarContainer"
218218 }
219− [ styled R.div'
220− { css: sidebarStyle
221− , className: "sidebarContainer"
219+ [ element M.animatePresence
220+ { children: [ guard sidebarOpen sb ]
222221 }
223− [ element M.animatePresence
224− { children: [ guard sidebarOpen sb ]
222+ , R.div_
223+ [ el M.h1
224+ { initial: M.initial (css { x: -10, opacity: 0 })
225+ , animate: M.animate $ css { x: [ -10, -3, 0 ], opacity: [ 0.1, 0.2, 1.0 ] }
226+ , transition: M.transition { duration: 0.6, times: [ 0.1, 0.4, 1.0 ] }
227+ , key: "non-sidebar-heading"
225228 }
226− , R.div_
227− [ el M.h1
228− { initial: M.initial (css { x: -10, opacity: 0 })
229− , animate: M.animate $ css { x: [ -10, -3, 0 ], opacity: [ 0.1, 0.2, 1.0 ] }
230− , transition: M.transition { duration: 0.6, times: [ 0.1, 0.4, 1.0 ] }
231− , key: "non-sidebar-heading"
232− }
233− [ R.text "Non-sidebar" ]
234− ]
229+ [ R.text "Non-sidebar" ]
235230 ]
236231 ]
237232 ]
233+ ]
238234
239235 variantLabels = makeVariantLabels variants
240236
src/Yoga/Prelude/View.purs+10−2
@@ -8,14 +8,22 @@ module Yoga.Prelude.View
88 , module React.Basic.DOM
99 , module React.Basic.DOM.Events
1010 , module Type.Row
11+ , module Web.DOM
12+ , module Data.Nullable
13+ , NodeRef
1114 ) where
1215
1316import Yoga.Prelude.Default
14−import Yoga (el, el_, reactComponent, reactComponentWithChildren, styled, styledLeaf, yogaElement)
15−import Yoga.Block.Internal (DivProps, DivPropsF, Id, InputProps, InputPropsF, OptionalProp(..), _0, appendIfDefined, createRef, dangerous, emotionDiv, emotionDiv_, emotionInput, getOr, getOrFlipped, ifTrue, isTruthy, maybeToOp, mkForwardRefComponent, mkForwardRefComponentEffect, opToMaybe, unsafeDiv, unsafeEmotion, unsafeUnOptional, (<>?), (?||))
17+import Data.Nullable (Nullable, notNull, null)
1618import Prim.Row (class Union)
1719import React.Basic.DOM (Props_div)
1820import React.Basic.DOM.Events (preventDefault, targetValue)
1921import React.Basic.Events (class Merge, EventFn, EventHandler, SyntheticEvent, handler, handler_, merge, mergeImpl, syntheticEvent, unsafeEventFn)
2022import React.Basic.Hooks (type (/\), Component, Hook, JSX, Pure, ReactChildren, ReactComponent, ReactContext, Ref, Render, UnsafeReference(..), UseContext, UseDebugValue, UseEffect, UseLayoutEffect, UseMemo, UseReducer, UseRef, UseState, coerceHook, consumer, contextConsumer, contextProvider, createContext, displayName, element, elementKeyed, empty, fragment, keyed, memo, provider, reactChildrenFromArray, reactChildrenToArray, reactComponentFromHook, readRef, readRefMaybe, unsafeHook, unsafeRenderEffect, useContext, useDebugValue, useEffect, useEffectAlways, useEffectOnce, useLayoutEffect, useLayoutEffectAlways, useLayoutEffectOnce, useMemo, useReducer, useRef, useState, useState', writeRef, (/\))
2123import Type.Row (type (+))
24+import Web.DOM (Node)
25+import Yoga (el, el_, styled, styledLeaf, yogaElement)
26+import Yoga.Block.Internal (DivProps, DivPropsF, Id, InputProps, InputPropsF, OptionalProp(..), _0, appendIfDefined, createRef, dangerous, emotionDiv, emotionInput, getOr, getOrFlipped, ifTrue, isTruthy, maybeToOp, mkForwardRefComponent, mkForwardRefComponentEffect, opToMaybe, unsafeDiv, unsafeEmotion, unsafeUnOptional, (<>?), (?||))
27+
28+type NodeRef =
29+ Ref (Nullable Node)
yarn.lock+4−4
@@ -4849,10 +4849,10 @@ fragment-cache@^0.2.1:
48494849 dependencies:
48504850 map-cache "^0.2.2"
48514851
4852−framer-motion@3.0.0-rc.22:
4853− version "3.0.0-rc.22"
4854− resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-3.0.0-rc.22.tgz#9ce43e5be6dd7f79c26d12eac5c5d0dca3bbeacf"
4855− integrity sha512-PwJReGpi/+lvNlpQ50nFFTfZkcZmqLBcYMBjKWNhQQ8zHB1aEGHK5mfeR4k/QVLlZPs7b/8sBuzYnnR7vwxsfg==
4852+framer-motion@^3.0.0:
4853+ version "3.0.0-rc.24"
4854+ resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-3.0.0-rc.24.tgz#38c041606b9ae21f82fd23c57b5d7e4a48ff4e44"
4855+ integrity sha512-cmJFyQoEWI6cxMYhtwreP1mVB0TFDJusAOIoq+M31wM4oQkCLxdkvU5ZGbERB8grkGVJg88NCRgnhXs0heCHrg==
48564856 dependencies:
48574857 framesync "^4.1.0"
48584858 hey-listen "^1.0.8"