git.iko.soy/rowtype-yoga/ry-blocks
on main help sign in
Add slider
commit8fae5e491914e2315ac8fa741aa3d883a7988385 authorMark Eibes <mark.eibes@gmail.com> dateSun 9 Aug 2020, 00:32 (6 years ago) parentceece1f
27 files changed+1146−68
.storybook/main.js+7 .storybook/preview-head.html+1 package.json+1 spago.dhall+1 src/Components/Cluster/Story.purs+23−17 src/Components/Cluster/Style.purs+6−4 src/Components/Cluster/View.purs+1−4 src/Components/Container/Story.purs+41−1 src/Components/Container/Style.purs+141−5 src/Components/Motion/Story.purs+201 src/Components/Range.purs+5 src/Components/Range/Spec.purs+20 src/Components/Range/Story.purs+54 src/Components/Range/Style.purs+126 src/Components/Range/View.purs+67 src/Components/Sidebar/Story.purs+12 src/Components/Sidebar/View.purs+1−4 src/Components/Stack/View.purs+1−1 src/Framer/Motion.js+9 src/Framer/Motion.purs+133−17 src/Prelude/Style.purs+1−1 src/Yoga.purs+25−6 src/Yoga/Blocks/Internal.js+17 src/Yoga/Blocks/Internal.purs+224−7 src/Yoga/Blocks/Internal/CSS.purs+8 src/Yoga/Blocks/Internal/OptionalProp.purs+2−1 yarn.lock+18
.storybook/main.js+7
@@ -1,7 +1,14 @@
1+const path = require('path');
2+const webpack = require('webpack');
3+
14module.exports = {
25 stories: ['../output/**/*.Story/index.js'],
36 addons: [],
47 webpackFinal: async config => {
8+ config.plugins.push(new webpack.SourceMapDevToolPlugin({
9+ append: '\n//# sourceMappingURL=./[url]',
10+ }))
11+
512 // do mutation to the config
613 return config;
714 },
.storybook/preview-head.htmlnew file+1
@@ -0,0 +1 @@
1+<link href="https://rsms.me/inter/inter.css" rel="stylesheet">
package.json+1
@@ -24,6 +24,7 @@
2424 "purescript": "^0.13.8",
2525 "react-refresh": "^0.8.3",
2626 "rimraf": "^3.0.2",
27+ "source-map-loader": "^1.0.1",
2728 "spago": "^0.15.3",
2829 "svg2psreact": "^2.1.0",
2930 "webpack": "^4.43.0",
spago.dhall+1
@@ -6,6 +6,7 @@ You can edit this file as you like.
66, dependencies =
77 [ "console"
88 , "effect"
9+ , "heterogeneous"
910 , "psci-support"
1011 , "react-basic-dom"
1112 , "react-basic-emotion"
src/Components/Cluster/Story.purs+23−17
@@ -1,14 +1,16 @@
11module Components.Cluster.Story where
22
33import Prelude
4−import Components.Container.Style as Styles
54import Components.Cluster as Cluster
5+import Components.Container.Style as Styles
6+import Data.Monoid (power)
67import Effect (Effect)
78import Effect.Unsafe (unsafePerformEffect)
89import React.Basic (JSX, element, fragment)
910import React.Basic.DOM (css)
1011import React.Basic.DOM as R
1112import React.Basic.Emotion as E
13+import Yoga (el)
1214
1315default ∷
1416 { decorators ∷ Array (Effect JSX -> JSX)
@@ -31,25 +33,29 @@ cluster =
3133 $ fragment
3234 [ R.div_
3335 [ R.h2_ [ R.text "No Options" ]
34− , element Cluster.component
35− { children:
36− [ R.div_
37− [ R.div { children: [ R.text "Child 1" ], style: css { backgroundColor: "teal" } }
38− , R.div { children: [ R.text "Child 2" ], style: css { backgroundColor: "rebeccapurple" } }
39− ]
40− ]
41− , style: css { backgroundColor: "hotpink" }
36+ , el Cluster.component
37+ { style: css { backgroundColor: "hotpink" }
4238 }
43− , R.h2_ [ R.text "Zero Space" ]
44− , element Cluster.component
45− { children:
46− [ R.div_
47− [ R.div { children: [ R.text "Child 1" ], style: css { backgroundColor: "teal" } }
48− , R.div { children: [ R.text "Child 2" ], style: css { backgroundColor: "rebeccapurple" } }
39+ [ R.div_
40+ $ [ power
41+ ( R.div
42+ { children: [ R.text "Content" ]
43+ , style: css { backgroundColor: "teal" }
44+ }
45+ )
46+ 30
4947 ]
50− ]
51− , style: css { backgroundColor: "darkslateblue" }
48+ ]
49+ , R.h2_ [ R.text "Zero Space" ]
50+ , el Cluster.component
51+ { style: css { backgroundColor: "darkslateblue" }
5252 , space: "0"
53+ , justify: "flex-end"
5354 }
55+ [ R.div_
56+ [ R.div { children: [ R.text "Child 1" ], style: css { backgroundColor: "teal" } }
57+ , R.div { children: [ R.text "Child 2" ], style: css { backgroundColor: "rebeccapurple" } }
58+ ]
59+ ]
5460 ]
5561 ]
src/Components/Cluster/Style.purs+6−4
@@ -5,6 +5,8 @@ import Prelude.Style
55type Props f r =
66 ( css ∷ f Style
77 , space ∷ f String
8+ , justify ∷ f String
9+ , align ∷ f String
810 | r
911 )
1012
@@ -17,12 +19,12 @@ cluster props = styles <>? props.css
1719 nest
1820 { display: flex
1921 , flexWrap: wrap
20− , alignItems: center
21− , justifyContent: flexStart
22− , margin: "calc(" <> props.space ?|| "1rem" <> "/2 * -1)" # str
22+ , alignItems: (str <$> props.align) ?|| center
23+ , justifyContent: (str <$> props.justify) ?|| flexStart
24+ , margin: "calc(" <> props.space ?|| "var(--s1)" <> "/2 * -1)" # str
2325 }
2426 , "& > * > *":
2527 nest
26− { margin: "calc(" <> (props.space ?|| "1rem") <> "/2)" # str
28+ { margin: "calc(" <> props.space ?|| "var(--s1)" <> "/2)" # str
2729 }
2830 }
src/Components/Cluster/View.purs+1−4
@@ -14,10 +14,7 @@ type Props =
1414type PropsOptional =
1515 PropsF OptionalProp
1616
17−component ∷
18− ∀ p p_.
19− Union p p_ Props =>
20− ReactComponent { | p }
17+component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
2118component =
2219 mkForwardRefComponent "Cluster" do
2320 \(props ∷ { | PropsOptional }) ref -> React.do
src/Components/Container/Story.purs+41−1
@@ -1,14 +1,54 @@
11module Components.Container.Story where
22
33import Prelude
4+import Components.Cluster as Cluster
45import Components.Container as Container
6+import Components.Container.Style (inputFocus)
7+import Components.Stack as Stack
58import Effect (Effect)
69import React.Basic (JSX, element)
710import React.Basic.DOM as R
811import React.Basic.Hooks (reactChildrenFromArray)
12+import Yoga (el, styled, styledLeaf)
913
1014default ∷ { title ∷ String }
1115default = { title: "Pages/Container" }
1216
1317container ∷ Effect JSX
14−container = pure (element Container.component { children: reactChildrenFromArray [ R.text "Content" ] })
18+container =
19+ pure
20+ ( element Container.component
21+ { children:
22+ reactChildrenFromArray
23+ [ R.text "Content"
24+ , el Stack.component {}
25+ [ el Cluster.component {}
26+ [ R.div_
27+ [ R.input { value: "Text" }
28+ , R.input { type: "number", value: "0" }
29+ , styledLeaf R.input'
30+ { className: "styledinput"
31+ , css: inputFocus
32+ , value: "focus"
33+ }
34+ , R.input
35+ { className: "styledinput"
36+ , value: "focus"
37+ , disabled: true
38+ }
39+ ]
40+ ]
41+ , R.input { type: "file" }
42+ , el Cluster.component {}
43+ [ R.div_
44+ [ R.input { type: "checkbox" }
45+ , R.input { type: "checkbox", checked: true }
46+ , R.input { type: "radio" }
47+ , R.input { type: "radio", checked: true }
48+ ]
49+ ]
50+ , R.input { type: "range" }
51+ ]
52+ ]
53+ }
54+ )
src/Components/Container/Style.purs+141−5
@@ -11,6 +11,24 @@ global =
1111 { minHeight: 100.0 # vh
1212 , minWidth: 100.0 # vw
1313 }
14+ , ":root":
15+ nested
16+ $ css
17+ { "--white": "#f7f4f0" # str
18+ , "--black": "#020207" # str
19+ , "--bg-col": "var(--white)" # str
20+ , "--input-col": "rgb(200,200,200)" # str
21+ , "--border-col": "rgb(118,118,118)" # str
22+ , "--text-col": "var(--black)" # str
23+ , "@media (prefers-color-scheme: dark)":
24+ nest
25+ { "--bg-col": "var(--black)" # str
26+ , "--input-col": "rgb(43,43,43)" # str
27+ , "--border-col": "rgb(195,195,195)" # str
28+ , "--text-col": "var(--white)" # str
29+ }
30+ }
31+ <> variables
1432 , html:
1533 nested
1634 $ css
@@ -19,26 +37,144 @@ global =
1937 , body:
2038 nested
2139 $ css
22− { fontFamily: str "system-ui, sans-serif"
23− , color: str "#f7f7f0"
24− , background: str "linear-gradient(to bottom right, #10354a, #002334)"
40+ { fontFamily: str "Inter, system-ui, sans-serif"
41+ , background: str "var(--bg-col)"
42+ , color: str "var(--text-col)"
2543 , margin: str "0"
2644 }
45+ <> colourTheme defaultColours
46+ , "h1,h2,h3,h4,h5":
47+ nest
48+ { fontWeight: str "800"
49+ }
2750 , h1:
2851 nested
2952 $ css
3053 { fontSize: em 3.5
31− , fontWeight: str "black"
3254 }
3355 , h2:
3456 nested
3557 $ css
3658 { fontSize: em 2.7
37− , fontWeight: str "black"
3859 }
3960 , "*, *:before, *:after":
4061 nested
4162 $ css
4263 { boxSizing: str "inherit"
4364 }
65+ , input
66+ }
67+
68+defaultColours ∷ Colours
69+defaultColours =
70+ { light:
71+ { background: "#FEFEFE"
72+ , highlight: "#0099FF"
73+ , text: "#333333"
74+ , input:
75+ { background: "#DDD"
76+ , textDisabled: "#999999"
77+ , backgroundDisabled: "#F0F0F0"
78+ }
79+ }
80+ , dark:
81+ { background: "#111"
82+ , highlight: "#0099FF"
83+ , text: "#FFE9D7"
84+ , input:
85+ { background: "#444444"
86+ , textDisabled: "#666"
87+ , backgroundDisabled: "#222"
88+ }
89+ }
90+ }
91+
92+type ColoursVariant =
93+ { background ∷ String
94+ , highlight ∷ String
95+ , text ∷ String
96+ , input ∷
97+ { background ∷ String
98+ , textDisabled ∷ String
99+ , backgroundDisabled ∷ String
100+ }
101+ }
102+
103+type Colours =
104+ { dark ∷ ColoursVariant
105+ , light ∷ ColoursVariant
106+ }
107+
108+colourTheme ∷ Colours -> Style
109+colourTheme { dark, light } =
110+ css
111+ -- Dark
112+ { "--bg-col-inverted": dark.background # str
113+ , "--text-col-inverted": dark.text # str
114+ , "--highlight-col-inverted": dark.highlight # str
115+ , "--input-bg-col-inverted": dark.input.background # str
116+ , "--input-bg-col-disabled-inverted": dark.input.backgroundDisabled # str
117+ , "--input-text-col-disabled-inverted": dark.input.textDisabled # str
118+ -- Light
119+ , "--bg-col": light.background # str
120+ , "--text-col": light.text # str
121+ , "--highlight-col": light.highlight # str
122+ , "--input-bg-col": light.input.background # str
123+ , "--input-bg-col-disabled": light.input.backgroundDisabled # str
124+ , "--input-text-col-disabled": light.input.textDisabled # str
125+ , "@media (prefers-color-scheme: dark)":
126+ nest
127+ { "--bg-col-inverted": light.background # str
128+ , "--text-col-inverted": light.text # str
129+ , "--highlight-col-inverted": light.highlight # str
130+ , "--input-bg-col-inverted": light.input.background # str
131+ , "--input-bg-col-disabled-inverted": light.input.backgroundDisabled # str
132+ , "--input-text-col-disabled-inverted": light.input.textDisabled # str
133+ -- Light
134+ , "--bg-col": dark.background # str
135+ , "--text-col": dark.text # str
136+ , "--highlight-col": dark.highlight # str
137+ , "--input-bg-col": dark.input.background # str
138+ , "--input-bg-col-disabled": dark.input.backgroundDisabled # str
139+ , "--input-text-col-disabled": dark.input.textDisabled # str
140+ }
141+ }
142+
143+variables ∷ Style
144+variables =
145+ css
146+ { "--ratio": "1.5" # str
147+ , "--s-5": str "calc(var(--s-4) / var(--ratio))"
148+ , "--s-4": str "calc(var(--s-3) / var(--ratio))"
149+ , "--s-3": str "calc(var(--s-2) / var(--ratio))"
150+ , "--s-2": str "calc(var(--s-1) / var(--ratio))"
151+ , "--s-1": str "calc(var(--s0) / var(--ratio))"
152+ , "--s0": 1.0 # rem
153+ , "--s1": str "calc(var(--s0) * var(--ratio))"
154+ , "--s2": str "calc(var(--s1) * var(--ratio))"
155+ , "--s3": str "calc(var(--s2) * var(--ratio))"
156+ , "--s4": str "calc(var(--s3) * var(--ratio))"
157+ , "--s5": str "calc(var(--s4) * var(--ratio))"
158+ }
159+
160+input ∷ StyleProperty
161+input =
162+ nest
163+ { backgroundColor: "var(--input-bg-col)" # str
164+ , padding: "5px" # str
165+ , border: str "1px solid var(--bg-col)"
166+ , borderRadius: "5px" # str
167+ , fontSize: "12px" # str
168+ , paddingBottom: "4px" # str
169+ , paddingLeft: "8px" # str
170+ , "&:disabled": nest { color: str "var(--input-text-col-disabled)" }
171+ , "&:focus": nested inputFocus
172+ }
173+
174+-- Standalone style for storybook
175+inputFocus ∷ Style
176+inputFocus =
177+ css
178+ { outline: none
179+ , border: str "1px solid var(--highlight-col)"
44180 }
src/Components/Motion/Story.pursnew file+201
@@ -0,0 +1,201 @@
1+module Components.Motion.Story where
2+
3+import Prelude
4+import Components.Centre as Centre
5+import Components.Container.Style as Styles
6+import Components.Sidebar as Sidebar
7+import Data.Monoid (guard)
8+import Data.Tuple (Tuple(..))
9+import Data.Tuple.Nested ((/\))
10+import Effect (Effect)
11+import Effect.Unsafe (unsafePerformEffect)
12+import Framer.Motion (makeVariantLabels, withMotion)
13+import Framer.Motion as M
14+import React.Basic (JSX, element, fragment)
15+import React.Basic.DOM (css)
16+import React.Basic.DOM as R
17+import React.Basic.Emotion as E
18+import React.Basic.Events (handler_)
19+import React.Basic.Hooks (useState)
20+import React.Basic.Hooks as React
21+import Yoga (el, reactComponent, styled)
22+import Yoga.Blocks.Internal (_0, center, flex)
23+import Yoga.Blocks.Internal.CSS (_100percent)
24+
25+default ∷
26+ { decorators ∷ Array (Effect JSX -> JSX)
27+ , title ∷ String
28+ }
29+default =
30+ { title: "Motion"
31+ , decorators:
32+ [ \storyFn ->
33+ R.div_
34+ [ element E.global { styles: Styles.global }
35+ , unsafePerformEffect storyFn
36+ ]
37+ ]
38+ }
39+
40+motion ∷ Effect JSX
41+motion = do
42+ mc <- mkMc
43+ pure $ element mc {}
44+ where
45+ mkMc = do
46+ motionCentre <- M.custom Centre.component
47+ pure
48+ $ reactComponent "MotionTest" \{} -> React.do
49+ Tuple isOpen setIsOpen <- React.useState false
50+ pure
51+ $ fragment
52+ [ E.element R.div'
53+ { className: "bg"
54+ , css: backgroundStyle
55+ , children:
56+ [ E.element motionCentre
57+ ( { className: "parent"
58+ , css: parentStyle <> if isOpen then parentStyleOpen else mempty
59+ , onClick: handler_ (setIsOpen not)
60+ , style: css { y: if isOpen then -70 else 0, skew: if isOpen then 30 else 0 }
61+ }
62+ `withMotion`
63+ { layout: true
64+ , initial: css { borderRadius: 50 }
65+ }
66+ )
67+ ]
68+ }
69+ ]
70+
71+ backgroundStyle ∷ E.Style
72+ backgroundStyle =
73+ E.css
74+ { background: E.str "#da36dd"
75+ , height: E.vh 88.0
76+ , borderRadius: E.px 8
77+ , display: flex
78+ , alignItems: center
79+ , justifyContent: center
80+ }
81+
82+ parentStyle ∷ E.Style
83+ parentStyle =
84+ E.css
85+ { width: E.px 100
86+ , height: E.px 100
87+ , padding: _0
88+ , margin: _0
89+ , display: flex
90+ , alignItems: center
91+ , justifyContent: center
92+ , boxShadow: E.str "30px 30px 60px #b92ebc, -30px -30px 60px #fb3efe"
93+ , background: E.str "linear-gradient(145deg, #e93aec, #c431c7)"
94+ }
95+
96+ childStyle ∷ E.Style
97+ childStyle =
98+ E.css
99+ { background: E.str "hotpink"
100+ , width: E.px 40
101+ , height: E.px 40
102+ , borderRadius: E.percent 50.0
103+ , padding: _0
104+ , margin: _0
105+ }
106+
107+ parentStyleOpen ∷ E.Style
108+ parentStyleOpen =
109+ E.css
110+ { width: E.px 300
111+ , height: E.px 300
112+ , boxShadow: E.str "50px 50px 60px #b92ebc, -50px -50px 60px #fb3efe"
113+ , background: E.str "linear-gradient(145deg, #e93aec, #c431c7)"
114+ }
115+
116+animatedSidebar ∷ Effect JSX
117+animatedSidebar = do
118+ mc <- mkMc
119+ pure $ element mc {}
120+ where
121+ mkMc = do
122+ pure
123+ $ reactComponent "MotionTest" \{} -> React.do
124+ sidebarOpen /\ setSidebarOpen <- useState true
125+ let
126+ sb =
127+ styled M.div
128+ { className: "sidebar"
129+ , css: if sidebarOpen then sidebarStyleOpen else sidebarStyleHidden
130+ , onClick: handler_ (setSidebarOpen not)
131+ , initial: M.initial $ css { opacity: 0 }
132+ , animate: M.animate $ css { opacity: 1, width: "200px" }
133+ , exit: M.exit $ css { opacity: 0 }
134+ , key: "sidebar"
135+ }
136+ [ R.text $ if sidebarOpen then "Sidebar" else "|||" ]
137+ pure
138+ $ styled R.div'
139+ { className: "bg"
140+ , css: backgroundStyle
141+ }
142+ [ el Sidebar.component
143+ { className: "parent"
144+ , css: sidebarContainerStyle
145+ }
146+ [ styled R.div'
147+ { css: sidebarStyle
148+ , className: "sidebarContainer"
149+ }
150+ [ el M.animatePresence {} [ guard sidebarOpen sb ]
151+ , R.div_
152+ [ el M.h1
153+ { initial: M.initial (css { x: -10, opacity: 0 })
154+ , animate: M.animate $ css { x: [ -10, -3, 0 ], opacity: [ 0.1, 0.2, 1.0 ] }
155+ , transition: M.transition { duration: 0.6, times: [ 0.1, 0.4, 1.0 ] }
156+ , key: "non-sidebar-heading"
157+ }
158+ [ R.text "Non-sidebar" ]
159+ ]
160+ ]
161+ ]
162+ ]
163+
164+ variantLabels = makeVariantLabels variants
165+
166+ variants =
167+ { hidden: { width: 30, height: 30, borderRadius: "50%" }
168+ , show: { width: "inherit", height: "100%" }
169+ }
170+
171+ sidebarContainerStyle ∷ E.Style
172+ sidebarContainerStyle =
173+ E.css
174+ { height: _100percent
175+ , zIndex: E.str "40"
176+ }
177+
178+ sidebarStyle ∷ E.Style
179+ sidebarStyle =
180+ E.css
181+ { height: _100percent
182+ }
183+
184+ sidebarStyleOpen ∷ E.Style
185+ sidebarStyleOpen =
186+ E.css
187+ { background: E.str "teal"
188+ }
189+
190+ sidebarStyleHidden ∷ E.Style
191+ sidebarStyleHidden =
192+ E.css
193+ { background: E.str "darkslate"
194+ }
195+
196+ backgroundStyle ∷ E.Style
197+ backgroundStyle =
198+ E.css
199+ { background: E.str "darkslateblue"
200+ , height: E.vh 80.0
201+ }
src/Components/Range.pursnew file+5
@@ -0,0 +1,5 @@
1+module Components.Range
2+ ( module Components.Range.View
3+ ) where
4+
5+import Components.Range.View (component, Props)
src/Components/Range/Spec.pursnew file+20
@@ -0,0 +1,20 @@
1+module Components.Range.Spec where
2+
3+import Prelude.Spec
4+import Components.Range as Range
5+import React.Basic.DOM as R
6+
7+spec ∷ Spec Unit
8+spec =
9+ after_ cleanup do
10+ describe "The range" do
11+ it "renders without errors" do
12+ void
13+ $ renderComponent Range.component {}
14+ it "accepts div props" do
15+ { findByText } <-
16+ renderComponent Range.component
17+ { role: "Heinz"
18+ }
19+ elem <- findByText "Find me!"
20+ elem `shouldHaveAttribute` "role"
src/Components/Range/Story.pursnew file+54
@@ -0,0 +1,54 @@
1+module Components.Range.Story where
2+
3+import Prelude
4+import Components.Container.Style as Styles
5+import Components.Range as Range
6+import Effect (Effect)
7+import Effect.Unsafe (unsafePerformEffect)
8+import React.Basic (JSX, element, fragment)
9+import React.Basic.DOM (css)
10+import React.Basic.DOM as R
11+import React.Basic.Emotion as E
12+import Yoga.Blocks.Internal (_0)
13+
14+default ∷
15+ { decorators ∷ Array (Effect JSX -> JSX)
16+ , title ∷ String
17+ }
18+default =
19+ { title: "Layout/Range"
20+ , decorators:
21+ [ \storyFn ->
22+ R.div_
23+ [ element E.global { styles: Styles.global }
24+ , unsafePerformEffect storyFn
25+ ]
26+ ]
27+ }
28+
29+range ∷ Effect JSX
30+range =
31+ pure
32+ $ fragment
33+ [ R.div_
34+ [ R.h2_ [ R.text "No Options" ]
35+ , element Range.component
36+ {}
37+ , R.h2_ [ R.text "Min and max" ]
38+ , element Range.component
39+ { min: 0
40+ , max: 10
41+ }
42+ , R.h2_ [ R.text "Controlled" ]
43+ , element Range.component
44+ { value: 88
45+ , style: css { width: "200px" }
46+ }
47+ , R.h2_ [ R.text "Disabled" ]
48+ , element Range.component
49+ { value: 88
50+ , style: css { width: "200px" }
51+ , disabled: true
52+ }
53+ ]
54+ ]
src/Components/Range/Style.pursnew file+126
@@ -0,0 +1,126 @@
1+module Components.Range.Style where
2+
3+import Prelude.Style
4+import React.Basic.Emotion (inlineBlock)
5+
6+type Props f r =
7+ ( css ∷ f Style
8+ , space ∷ f StyleProperty
9+ , splitAfter ∷ f Int
10+ | r
11+ )
12+
13+range ∷ ∀ p. { | Props OptionalProp p } -> Style
14+range props = splitStyles <> styles <>? props.css
15+ where
16+ styles =
17+ css
18+ { position: str "relative"
19+ , width: percent 100.0
20+ , height: str "var(--s0)"
21+ , display: inlineBlock
22+ , background: str "white"
23+ , borderWidth: _0
24+ }
25+
26+ splitStyles = props.splitAfter # foldMap \n -> onlyChildStyle <> nthChildStyle n
27+ where
28+ onlyChildStyle =
29+ css
30+ { "&:only-child": nest { height: 100.0 # percent }
31+ }
32+
33+ nthChild n = "& > :nth-child(" <> show n <> ")"
34+
35+ nthChildStyle n = (nthChild n) ~: { marginBottom: auto }
36+
37+container ∷ Style
38+container =
39+ css
40+ { position: relative
41+ -- , background: str "hotpink"
42+ , width: _100percent
43+ , "input[type=range]":
44+ nest
45+ { appearance: none
46+ , background: str "transparent"
47+ , margin: _0
48+ , padding: _0
49+ , width: _100percent
50+ }
51+ , "input[type=range]:focus":
52+ nest
53+ { outline: none
54+ , border: none
55+ }
56+ , "input[type=range]::-webkit-slider-thumb": nested thumbStyle
57+ , "input[type=range]::-moz-range-thumb": nested thumbStyle
58+ }
59+
60+thumbStyle ∷ Style
61+thumbStyle =
62+ css
63+ { appearance: none
64+ , width: str "var(--s0)"
65+ , height: str "var(--s0)"
66+ , borderRadius: 50.0 # percent
67+ , background: str "white"
68+ , boxShadow: str "0 calc(var(--s-4)/2) var(--s-3) rgba(70,70,70,0.6)"
69+ }
70+
71+inputDisabled ∷ Style
72+inputDisabled =
73+ css
74+ { "input[type=range]::-webkit-slider-thumb": nested thumbStyleDisabled
75+ , "input[type=range]::-moz-range-thumb": nested thumbStyleDisabled
76+ }
77+ where
78+ thumbStyleDisabled =
79+ css
80+ { background: str "#fcfcfc"
81+ , boxShadow: str "0 calc(var(--s-4)/2) var(--s-3) rgba(88,88,88,0.2)"
82+ }
83+
84+focusCircle ∷ Style
85+focusCircle =
86+ css
87+ { width: str "var(--s0)"
88+ , pointerEvents: none
89+ , height: str "var(--s0)"
90+ , borderRadius: 50.0 # percent
91+ , left: str $ "calc(var(--val)/var(--max) * calc(100% - var(--s0)))"
92+ , border: str "1px solid var(--highlight-col)"
93+ , boxShadow: str "0 0 var(--s-3) --var(--highlight-col)"
94+ , position: absolute
95+ , transform: str "scale(1.1)"
96+ , zIndex: str "12"
97+ }
98+
99+track ∷ Style
100+track =
101+ css
102+ { top: str "calc(var(--s0)/2.3)"
103+ , height: str "var(--s-3)"
104+ , borderRadius: str "calc(var(--s-3)/2)"
105+ , position: absolute
106+ }
107+
108+disabled ∷ Style
109+disabled = css { backgroundColor: str "var(--input-bg-col-disabled)" }
110+
111+filled ∷ Style
112+filled =
113+ track
114+ <> css
115+ { width: str "calc(var(--val)/var(--max) * 100%)"
116+ , backgroundColor: str "var(--highlight-col)"
117+ }
118+
119+notFilled ∷ Style
120+notFilled =
121+ track
122+ <> css
123+ { width: str "calc((1 - (var(--val)/var(--max))) * 100%)"
124+ , right: _0
125+ , backgroundColor: str "var(--input-bg-col)"
126+ }
src/Components/Range/View.pursnew file+67
@@ -0,0 +1,67 @@
1+module Components.Range.View (component, Props, PropsF) where
2+
3+import Prelude.View
4+import Components.Range.Style as Style
5+import Data.Int as Int
6+import React.Basic.DOM (css)
7+import React.Basic.DOM as R
8+import React.Basic.DOM.Events as Event
9+import React.Basic.Hooks as React
10+import Web.HTML.HTMLElement (tabIndex)
11+
12+type PropsF f =
13+ ( className ∷ f String
14+ , min ∷ f Int
15+ , max ∷ f Int
16+ , value ∷ f Int
17+ | Style.Props f InputProps
18+ )
19+
20+type Props =
21+ PropsF Id
22+
23+type PropsOptional =
24+ PropsF OptionalProp
25+
26+component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
27+component =
28+ mkForwardRefComponent "Range" do
29+ \(props ∷ { | PropsOptional }) ref -> React.do
30+ let min = props.min ?|| 0
31+ let max = props.max ?|| 100
32+ let v = props.value ?|| ((max - min) / 2)
33+ let disabled = props.disabled
34+ value /\ setValue <- useState' v
35+ hasFocus /\ setHasFocus <- useState' false
36+ pure
37+ $ styled R.div'
38+ { className: "ry-range"
39+ , css: Style.container <> guard props.disabled Style.inputDisabled
40+ , onFocus: handler_ $ setHasFocus true
41+ , onBlur: handler_ $ setHasFocus false
42+ , style: props.style <> css { "--val": value, "--max": max - min }
43+ }
44+ [ styledLeaf R.div'
45+ { className: "ry-range-filled"
46+ , css: Style.filled <> guard props.disabled Style.disabled
47+ }
48+ , styledLeaf R.div'
49+ { className: "ry-range-not-filled"
50+ , css: Style.notFilled <> guard props.disabled Style.disabled
51+ }
52+ , guard hasFocus
53+ $ styledLeaf R.div'
54+ { className: "ry-range-focus-circle"
55+ , css: Style.focusCircle
56+ }
57+ , emotionInput (props { max = show max, min = show min, value = show value })
58+ { className: "ry-range-thumb " <>? props.className
59+ , css: Style.range props <> guard props.disabled Style.inputDisabled
60+ , style: props.style
61+ , tabIndex: -1
62+ , value: show value
63+ , type: "range"
64+ , onChange: handler Event.targetValue ((_ >>= Int.fromString) >>> (foldMap setValue))
65+ , ref
66+ }
67+ ]
src/Components/Sidebar/Story.purs+12
@@ -67,5 +67,17 @@ sidebar =
6767 , space: "2em"
6868 , side: SidebarRight
6969 }
70+ , R.h2_ [ R.text "No Stretch" ]
71+ , element Sidebar.component
72+ { children:
73+ [ R.div_
74+ [ R.div { children: [ R.text $ power "Content " 50 ], style: css { backgroundColor: "darkslateblue" } }
75+ , R.div { children: [ R.text "Sidebar" ], style: css { backgroundColor: "teal" } }
76+ ]
77+ ]
78+ , style: css { backgroundColor: "oldlace" }
79+ , noStretch: true
80+ , side: SidebarRight
81+ }
7082 ]
7183 ]
src/Components/Sidebar/View.purs+1−4
@@ -14,10 +14,7 @@ type Props =
1414type PropsOptional =
1515 PropsF OptionalProp
1616
17−component ∷
18− ∀ p p_.
19− Union p p_ Props =>
20− ReactComponent { | p }
17+component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
2118component =
2219 mkForwardRefComponent "Sidebar" do
2320 \(props ∷ { | PropsOptional }) ref -> React.do
src/Components/Stack/View.purs+1−1
@@ -5,7 +5,7 @@ import Components.Stack.Style as Style
55
66type PropsF f =
77 ( className ∷ f String
8− | Style.Props f Props_div
8+ | Style.Props f DivProps
99 )
1010
1111type Props =
src/Framer/Motion.js+9
@@ -1,5 +1,14 @@
11const framerMotion = require("framer-motion")
22
33exports.divImpl = framerMotion.motion.div
4+exports.h1Impl = framerMotion.motion.h1
45
56exports.infinity = Infinity
7+
8+exports.custom = (component) => () => {
9+ return framerMotion.motion.custom(component)
10+}
11+
12+exports.animatePresence = () => framerMotion.AnimatePresence
13+
14+exports.animateSharedLayout = () => framerMotion.AnimateSharedLayout
src/Framer/Motion.purs+133−17
@@ -1,29 +1,59 @@
11module Framer.Motion
22 ( animate
3+ , makeVariantLabels
4+ , MakeVariantLabel
35 , div
6+ , h1
7+ , custom
48 , Exit
9+ , exit
510 , MotionProps
11+ , initial
12+ , MotionPropsF
613 , Transition
714 , transition
815 , Initial
16+ , (>>)
17+ , variants
918 , Animate
1019 , Infinity
1120 , infinity
1221 , VariantLabel
22+ , Variants
23+ , layout
24+ , Layout
1325 , AnimationControls
26+ , withMotion
27+ , motion
28+ , animateSharedLayout
29+ , AnimateSharedLayoutProps
30+ , AnimateSharedLayoutType
31+ , switch
32+ , crossfade
33+ , AnimatePresenceProps
34+ , animatePresence
1435 ) where
1536
16−import Prim.Row (class Union)
17−import React.Basic (ReactComponent)
18−import React.Basic.DOM (CSS, Props_div, css)
37+import Prelude
38+import Data.Symbol (class IsSymbol, SProxy, reflectSymbol)
39+import Effect (Effect)
40+import Heterogeneous.Mapping (class HMapWithIndex, class MappingWithIndex, hmapWithIndex)
41+import Literals.Undefined (Undefined)
42+import Prim.Row (class Nub, class Union)
43+import React.Basic (JSX, ReactComponent)
44+import React.Basic.DOM (CSS, Props_div, Props_h1, css)
45+import Record (disjointUnion)
1946import Type.Row (type (+))
2047import Untagged.Coercible (class Coercible, coerce)
2148import Untagged.Union (type (|+|))
49+import Yoga.Blocks.Internal (Id)
2250
2351foreign import divImpl ∷ ∀ a. ReactComponent { | a }
2452
53+foreign import h1Impl ∷ ∀ a. ReactComponent { | a }
54+
2555type Transition =
26− CSS
56+ CSS |+| Undefined
2757
2858newtype VariantLabel = VariantLabel String
2959
@@ -31,36 +61,68 @@ data Target
3161 = Target
3262
3363type Exit =
34− CSS |+| Array VariantLabel
64+ CSS |+| Array VariantLabel |+| Undefined
3565
3666foreign import data AnimationControls ∷ Type
3767
3868type Animate =
39− CSS |+| String |+| Array VariantLabel |+| AnimationControls
69+ CSS
70+ |+| VariantLabel
71+ |+| CSS
72+ |+| Array VariantLabel
73+ |+| AnimationControls
74+ |+| Undefined
4075
4176type Initial =
42− Boolean |+| CSS |+| String |+| Array VariantLabel
77+ Boolean |+| CSS |+| VariantLabel |+| Array VariantLabel |+| Undefined
4378
44−type MotionProps r =
45− ( initial ∷ Initial
46− , animate ∷ Animate
47− , variants ∷ Array CSS
48− , transition ∷ Transition
49− , exit ∷ Exit
79+type Layout =
80+ Boolean |+| Undefined
81+
82+type Variants =
83+ CSS |+| Undefined
84+
85+type MotionPropsF f r =
86+ ( initial ∷ f Initial
87+ , animate ∷ f Animate
88+ , variants ∷ f Variants
89+ , transition ∷ f Transition
90+ , layout ∷ f Layout
91+ , exit ∷ f Exit
5092 | r
5193 )
5294
95+type MotionProps r =
96+ MotionPropsF Id r
97+
5398animate ∷ ∀ a. Coercible a Animate => a -> Animate
5499animate = coerce
55100
56101initial ∷ ∀ a. Coercible a Initial => a -> Initial
57102initial = coerce
58103
59−transition ∷ ∀ r. { | r } -> CSS
60−transition = css
104+transition ∷ ∀ r. { | r } -> Transition
105+transition = coerce <<< css
61106
62−variants ∷ ∀ a. Coercible a (Array VariantLabel) => a -> (Array VariantLabel)
63−variants = coerce
107+exit ∷ ∀ a. Coercible a Exit => a -> Exit
108+exit = coerce
109+
110+variants ∷ ∀ r. { | r } -> Variants
111+variants = coerce <<< css
112+
113+layout ∷ ∀ a. Coercible a Layout => a -> Layout
114+layout = coerce
115+
116+data MakeVariantLabel
117+ = MakeVariantLabel
118+
119+instance makeVariantLabels' ∷
120+ (IsSymbol sym) =>
121+ MappingWithIndex MakeVariantLabel (SProxy sym) a VariantLabel where
122+ mappingWithIndex MakeVariantLabel prop _ = VariantLabel (reflectSymbol prop)
123+
124+makeVariantLabels ∷ ∀ a b. HMapWithIndex MakeVariantLabel a b => a -> b
125+makeVariantLabels = hmapWithIndex MakeVariantLabel
64126
65127div ∷
66128 ∀ attrs attrs_.
@@ -68,6 +130,60 @@ div ∷
68130 ReactComponent { | attrs }
69131div = divImpl
70132
133+h1 ∷
134+ ∀ attrs attrs_.
135+ Union attrs attrs_ (MotionProps + Props_h1) =>
136+ ReactComponent { | attrs }
137+h1 = h1Impl
138+
139+withMotion ∷
140+ ∀ result baseProps motionSubset.
141+ Union baseProps (MotionProps ()) result => Nub result result => Coercible motionSubset { | MotionProps () } => Record baseProps -> motionSubset -> Record result
142+withMotion old new = disjointUnion old ((coerce new) ∷ { | MotionProps () })
143+
144+motion ∷
145+ ∀ result baseProps motionSubset.
146+ Union baseProps (MotionProps ()) result => Nub result result => Coercible motionSubset { | MotionProps () } => motionSubset -> Record baseProps -> Record result
147+motion = flip withMotion
148+
149+infixr 7 withMotion as >>
150+
71151foreign import data Infinity ∷ Type
72152
73153foreign import infinity ∷ Infinity
154+
155+foreign import custom ∷
156+ ∀ old.
157+ ReactComponent { | old } ->
158+ Effect (ReactComponent { | MotionProps old })
159+
160+type AnimatePresenceProps =
161+ ( initial ∷ Boolean
162+ , custom ∷ ∀ a. a
163+ , exitBeforeEnter ∷ Boolean
164+ , onExitComplete ∷ Effect Unit
165+ , children ∷ Array JSX
166+ )
167+
168+foreign import animatePresence ∷
169+ ∀ attrs attrs_.
170+ Union attrs attrs_ AnimatePresenceProps =>
171+ ReactComponent { | attrs }
172+
173+type AnimateSharedLayoutProps =
174+ ( type ∷ AnimateSharedLayoutType
175+ , children ∷ Array JSX
176+ )
177+
178+newtype AnimateSharedLayoutType = AnimateSharedLayoutType String
179+
180+switch ∷ AnimateSharedLayoutType
181+switch = AnimateSharedLayoutType "switch"
182+
183+crossfade ∷ AnimateSharedLayoutType
184+crossfade = AnimateSharedLayoutType "crossfade"
185+
186+foreign import animateSharedLayout ∷
187+ ∀ attrs attrs_.
188+ Union attrs attrs_ AnimateSharedLayoutProps =>
189+ ReactComponent { | attrs }
src/Prelude/Style.purs+1−1
@@ -6,6 +6,6 @@ module Prelude.Style
66 ) where
77
88import Prelude.Default
9−import React.Basic.Emotion (class IsStyle, class IsStyleProperty, Style, StyleProperty, ch, cm, color, css, element, elementKeyed, em, ex, fallbacks, global, important, inches, inherit, int, keyframes, merge, mm, nested, none, num, pc, percent, prop, pt, px, px', rem, str, style, unset, url, vh, vmax, vmin, vw)
9+import React.Basic.Emotion
1010import Yoga.Blocks.Internal.OptionalProp
1111import Yoga.Blocks.Internal.CSS
src/Yoga.purs+25−6
@@ -1,16 +1,15 @@
11module Yoga where
22
33import Prelude
4−import Data.Nullable (Nullable)
4+import Data.Function as F
5+import Data.Symbol (SProxy(..))
56import Effect.Unsafe (unsafePerformEffect)
6−import Foreign.Object (Object)
77import Prim.Row (class Lacks)
8−import React.Basic.DOM (CSS)
9−import React.Basic.Events (EventHandler)
10−import React.Basic.Hooks (JSX, ReactComponent, Ref, Render)
8+import React.Basic.Emotion as Emotion
9+import React.Basic.Hooks (JSX, ReactComponent, Render)
1110import React.Basic.Hooks as Hooks
11+import Record as Record
1212import Untagged.Coercible (class Coercible, coerce)
13−import Web.DOM (Node)
1413
1514reactComponent ∷
1615 ∀ hooks props.
@@ -33,3 +32,23 @@ reactComponentWithChildren = (map map map) unsafePerformEffect Hooks.reactCompon
3332
3433yogaElement ∷ ∀ allProps givenProps. Coercible givenProps (Record allProps) => ReactComponent (Record allProps) -> givenProps -> JSX
3534yogaElement el props = Hooks.element el (coerce props)
35+
36+el ∷
37+ ∀ props.
38+ Lacks "children" props =>
39+ ReactComponent { children ∷ Array JSX | props } ->
40+ Record props -> Array JSX -> JSX
41+el x props children = Hooks.element x (Record.insert (SProxy ∷ SProxy "children") children props)
42+
43+styled ∷
44+ ∀ props.
45+ Lacks "children" props =>
46+ ReactComponent { className ∷ String, children ∷ Array JSX | props } ->
47+ { className ∷ String, css ∷ Emotion.Style | props } -> Array JSX -> JSX
48+styled x props children = Emotion.element x (Record.insert (SProxy ∷ SProxy "children") children props)
49+
50+styledLeaf ∷
51+ ∀ props.
52+ ReactComponent { className ∷ String | props } ->
53+ { className ∷ String, css ∷ Emotion.Style | props } -> JSX
54+styledLeaf = Emotion.element
src/Yoga/Blocks/Internal.js+17
@@ -6,3 +6,20 @@ exports.mkForwardRefComponent = (displayName) => (renderFn) => {
66 return React.forwardRef(component);
77};
88
9+
10+exports.mkForwardRefComponentEffect = (displayName) => (renderFn) => () => {
11+ const component = (props, ref) => renderFn(props)(ref)();
12+ component.displayName = displayName;
13+ return React.forwardRef(component);
14+};
15+
16+
17+exports.pickDefinedFn = function (ks, r) {
18+ var copy = {};
19+ for (var i = 0; i < ks.length; i++) {
20+ if (r[ks[i]] !== undefined) {
21+ copy[ks[i]] = r[ks[i]];
22+ }
23+ }
24+ return copy;
25+};
src/Yoga/Blocks/Internal.purs+224−7
@@ -1,29 +1,43 @@
11module Yoga.Blocks.Internal
22 ( mkForwardRefComponent
3+ , mkForwardRefComponentEffect
34 , unsafeEmotion
5+ , unsafeDiv
46 , dangerous
57 , DivProps
68 , DivPropsF
9+ , InputProps
10+ , InputPropsF
711 , emotionDiv
12+ , emotionDiv_
13+ , emotionInput
814 , module Yoga.Blocks.Internal.OptionalProp
915 , module Yoga.Blocks.Internal.CSS
1016 ) where
1117
18+import Prelude
19+import Yoga.Blocks.Internal.OptionalProp
20+import Data.Array (fromFoldable)
21+import Data.Function.Uncurried (Fn2, runFn2)
1222import Data.Nullable (Nullable)
23+import Effect (Effect)
1324import Effect.Unsafe (unsafePerformEffect)
1425import Foreign.Object (Object)
1526import Prelude (Unit, (<<<))
1627import Prim.Row (class Union)
17−import React.Basic.DOM (unsafeCreateDOMComponent, CSS)
28+import Prim.Row as Row
29+import Prim.RowList as RL
30+import React.Basic.DOM (CSS, Props_div, Props_input, unsafeCreateDOMComponent)
1831import React.Basic.Emotion (Style)
1932import React.Basic.Emotion as E
2033import React.Basic.Events (EventHandler)
2134import React.Basic.Hooks (JSX, ReactComponent, Ref, Render)
22−import Record.Extra (pick)
35+import Record.Extra (class Keys, keys)
2336import Record.Unsafe.Union (unsafeUnion)
37+import Type.Data.Row (RProxy(..))
38+import Untagged.Coercible (class Coercible)
2439import Web.DOM (Node)
2540import Yoga.Blocks.Internal.CSS (_0, auto, borderBox, center, column, contentBox, flex, flexStart, left, nest, nestDynamic, right, (~:))
26−import Yoga.Blocks.Internal.OptionalProp
2741
2842foreign import mkForwardRefComponent ∷
2943 ∀ inputProps props a hooks.
@@ -31,8 +45,14 @@ foreign import mkForwardRefComponent ∷
3145 ({ | inputProps } -> Ref a -> Render Unit hooks JSX) ->
3246 ReactComponent { | props }
3347
34−unsafeEmotion ∷ ∀ propsA propsB ref. String -> Record propsA -> { className ∷ String, css ∷ E.Style, ref ∷ Ref ref | propsB } -> JSX
35−unsafeEmotion name propsA propsB = E.element (dangerous name) (unsafeUnion propsA propsB)
48+foreign import mkForwardRefComponentEffect ∷
49+ ∀ inputProps props a hooks.
50+ String ->
51+ ({ | inputProps } -> Ref a -> Render Unit hooks JSX) ->
52+ Effect (ReactComponent { | props })
53+
54+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
55+unsafeEmotion component propsA propsB = E.element component (unsafeUnion propsB propsA)
3656
3757emotionDiv_ ∷
3858 ∀ props props_.
@@ -44,13 +64,47 @@ emotionDiv_ ∷
4464 | props
4565 } ->
4666 JSX
47−emotionDiv_ = unsafeEmotion "div"
67+emotionDiv_ = unsafeEmotion unsafeDiv
68+
69+emotionDiv = emotionDiv_ <<< pickDefined
70+
71+foreign import pickDefinedFn ∷ ∀ r1 r2. Fn2 (Array String) (Record r1) (Record r2)
72+
73+pickDefined ∷
74+ ∀ a r b l.
75+ Row.Union b r a =>
76+ RL.RowToList b l =>
77+ Keys l =>
78+ Record a ->
79+ Record b
80+pickDefined = runFn2 pickDefinedFn ks
81+ where
82+ ks = fromFoldable $ keys (RProxy ∷ RProxy b)
83+
84+unsafeDiv = dangerous "div"
85+
86+emotionInput_ ∷
87+ ∀ props props_.
88+ Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | InputProps ) =>
89+ (Record (InputProps)) ->
90+ { className ∷ String
91+ , css ∷ Style
92+ , ref ∷ Ref (Nullable Node)
93+ | props
94+ } ->
95+ JSX
96+emotionInput_ = unsafeEmotion unsafeInput
97+
98+emotionInput = emotionInput_ <<< pickDefined
4899
49−emotionDiv = emotionDiv_ <<< pick
100+unsafeInput = dangerous "input"
50101
51102dangerous ∷ ∀ props. String -> ReactComponent (Record props)
52103dangerous = unsafePerformEffect <<< unsafeCreateDOMComponent
53104
105+-- type DivProps =
106+-- Props_div
107+
54108type DivProps =
55109 DivPropsF Id
56110
@@ -164,24 +218,187 @@ type DivPropsF f =
164218 , property ∷ f String
165219 , radioGroup ∷ f String
166220 , readOnly ∷ f Boolean
221+ -- , ref ∷ f (Ref (Nullable Node))
222+ , resource ∷ f String
223+ , role ∷ f String
224+ , rowSpan ∷ f Int
225+ , scoped ∷ f Boolean
226+ , seamless ∷ f Boolean
227+ , security ∷ f String
228+ , spellCheck ∷ f Boolean
229+ , srcDoc ∷ f JSX
230+ , srcLang ∷ f String
231+ , srcSet ∷ f String
232+ , style ∷ f CSS
233+ , suppressContentEditableWarning ∷ f Boolean
234+ , tabIndex ∷ f Int
235+ , title ∷ f String
236+ , typeof ∷ f String
237+ , unselectable ∷ f Boolean
238+ , useMap ∷ f String
239+ , vocab ∷ f String
240+ , wmode ∷ f String
241+ )
242+
243+type InputProps =
244+ InputPropsF Id
245+
246+type InputPropsF f =
247+ ( _aria ∷ f (Object String)
248+ , _data ∷ f (Object String)
249+ , about ∷ f String
250+ , accept ∷ f String
251+ , acceptCharset ∷ f String
252+ , accessKey ∷ f String
253+ , allowFullScreen ∷ f Boolean
254+ , alt ∷ f String
255+ , autoCapitalize ∷ f String
256+ , autoComplete ∷ f String
257+ , autoCorrect ∷ f String
258+ , autoFocus ∷ f Boolean
259+ , autoPlay ∷ f Boolean
260+ , autoSave ∷ f String
261+ , capture ∷ f Boolean
262+ , cellPadding ∷ f String
263+ , cellSpacing ∷ f String
264+ , charSet ∷ f String
265+ , checked ∷ f Boolean
266+ , classID ∷ f String
267+ , colSpan ∷ f Int
268+ , contentEditable ∷ f Boolean
269+ , contextMenu ∷ f String
270+ , crossOrigin ∷ f String
271+ , dangerouslySetInnerHTML ∷ f { __html ∷ f String }
272+ , datatype ∷ f String
273+ , dateTime ∷ f String
274+ , defaultChecked ∷ f String
275+ , defaultValue ∷ f String
276+ , dir ∷ f String
277+ , disabled ∷ f Boolean
278+ , draggable ∷ f Boolean
279+ , encType ∷ f String
280+ , form ∷ f String
281+ , formAction ∷ f String
282+ , formEncType ∷ f String
283+ , formMethod ∷ f String
284+ , formNoValidate ∷ f Boolean
285+ , formTarget ∷ f String
286+ , frameBorder ∷ f String
287+ , height ∷ f String
288+ , hidden ∷ f Boolean
289+ , hrefLang ∷ f String
290+ , htmlFor ∷ f String
291+ , httpEquiv ∷ f String
292+ , icon ∷ f String
293+ , id ∷ f String
294+ , inlist ∷ f String
295+ , inputMode ∷ f String
296+ , is ∷ f String
297+ , itemID ∷ f String
298+ , itemProp ∷ f String
299+ , itemRef ∷ f String
300+ , itemScope ∷ f Boolean
301+ , itemType ∷ f String
302+ , key ∷ f String
303+ , keyParams ∷ f String
304+ , keyType ∷ f String
305+ , lang ∷ f String
306+ , list ∷ f String
307+ , marginHeight ∷ f String
308+ , marginWidth ∷ f String
309+ , maxLength ∷ f Int
310+ , mediaGroup ∷ f String
311+ , minLength ∷ f Int
312+ , multiple ∷ f Boolean
313+ , name ∷ f String
314+ , noValidate ∷ f Boolean
315+ , onAnimationEnd ∷ f EventHandler
316+ , onAnimationIteration ∷ f EventHandler
317+ , onAnimationStart ∷ f EventHandler
318+ , onBlur ∷ f EventHandler
319+ , onChange ∷ f EventHandler
320+ , onClick ∷ f EventHandler
321+ , onCompositionEnd ∷ f EventHandler
322+ , onCompositionStart ∷ f EventHandler
323+ , onCompositionUpdate ∷ f EventHandler
324+ , onContextMenu ∷ f EventHandler
325+ , onCopy ∷ f EventHandler
326+ , onCut ∷ f EventHandler
327+ , onDoubleClick ∷ f EventHandler
328+ , onDrag ∷ f EventHandler
329+ , onDragEnd ∷ f EventHandler
330+ , onDragEnter ∷ f EventHandler
331+ , onDragExit ∷ f EventHandler
332+ , onDragLeave ∷ f EventHandler
333+ , onDragOver ∷ f EventHandler
334+ , onDragStart ∷ f EventHandler
335+ , onDrop ∷ f EventHandler
336+ , onFocus ∷ f EventHandler
337+ , onGotPointerCapture ∷ f EventHandler
338+ , onInvalid ∷ f EventHandler
339+ , onKeyDown ∷ f EventHandler
340+ , onKeyPress ∷ f EventHandler
341+ , onKeyUp ∷ f EventHandler
342+ , onLostPointerCapture ∷ f EventHandler
343+ , onMouseDown ∷ f EventHandler
344+ , onMouseEnter ∷ f EventHandler
345+ , onMouseLeave ∷ f EventHandler
346+ , onMouseMove ∷ f EventHandler
347+ , onMouseOut ∷ f EventHandler
348+ , onMouseOver ∷ f EventHandler
349+ , onMouseUp ∷ f EventHandler
350+ , onPaste ∷ f EventHandler
351+ , onPointerCancel ∷ f EventHandler
352+ , onPointerDown ∷ f EventHandler
353+ , onPointerEnter ∷ f EventHandler
354+ , onPointerLeave ∷ f EventHandler
355+ , onPointerMove ∷ f EventHandler
356+ , onPointerOut ∷ f EventHandler
357+ , onPointerOver ∷ f EventHandler
358+ , onPointerUp ∷ f EventHandler
359+ , onSelect ∷ f EventHandler
360+ , onSubmit ∷ f EventHandler
361+ , onTouchCancel ∷ f EventHandler
362+ , onTouchEnd ∷ f EventHandler
363+ , onTouchMove ∷ f EventHandler
364+ , onTouchStart ∷ f EventHandler
365+ , onTransitionEnd ∷ f EventHandler
366+ , onWheel ∷ f EventHandler
367+ , pattern ∷ f String
368+ , placeholder ∷ f String
369+ , prefix ∷ f String
370+ , property ∷ f String
371+ , radioGroup ∷ f String
372+ , readOnly ∷ f Boolean
167373 , ref ∷ f (Ref (Nullable Node))
374+ , required ∷ f Boolean
168375 , resource ∷ f String
376+ , results ∷ f String
169377 , role ∷ f String
170378 , rowSpan ∷ f Int
171379 , scoped ∷ f Boolean
172380 , seamless ∷ f Boolean
173381 , security ∷ f String
382+ , size ∷ f Int
174383 , spellCheck ∷ f Boolean
384+ , src ∷ f String
175385 , srcDoc ∷ f JSX
176386 , srcLang ∷ f String
177387 , srcSet ∷ f String
388+ , step ∷ f String
178389 , style ∷ f CSS
179390 , suppressContentEditableWarning ∷ f Boolean
180391 , tabIndex ∷ f Int
181392 , title ∷ f String
393+ , title ∷ f String
394+ , type ∷ f String
182395 , typeof ∷ f String
183396 , unselectable ∷ f Boolean
184397 , useMap ∷ f String
398+ , value ∷ f String
185399 , vocab ∷ f String
400+ , width ∷ f String
186401 , wmode ∷ f String
402+ , min ∷ f (String)
403+ , max ∷ f (String)
187404 )
src/Yoga/Blocks/Internal/CSS.purs+8
@@ -19,6 +19,12 @@ right = str "right"
1919auto ∷ StyleProperty
2020auto = str "auto"
2121
22+relative ∷ StyleProperty
23+relative = str "relative"
24+
25+absolute ∷ StyleProperty
26+absolute = str "absolute"
27+
2228contentBox ∷ StyleProperty
2329contentBox = str "content-box"
2430
@@ -28,6 +34,8 @@ borderBox = str "border-box"
2834_0 ∷ StyleProperty
2935_0 = str "0"
3036
37+_100percent = percent 100.0
38+
3139flex = str "flex"
3240
3341hidden = str "hidden"
src/Yoga/Blocks/Internal/OptionalProp.purs+2−1
@@ -6,6 +6,7 @@ import Data.Foldable (class Foldable, foldMap, foldl, foldr)
66import Data.Maybe (Maybe, maybe)
77import Data.Newtype (class Newtype)
88import Unsafe.Coerce (unsafeCoerce)
9+import Untagged.Coercible (class Coercible)
910import Untagged.Union (UndefinedOr, defined, fromUndefinedOr, maybeToUor, uorToMaybe)
1011
1112type Id a =
@@ -55,7 +56,7 @@ ifTrue v alt x = if (x ?|| false) then v else alt
5556isTruthy ∷ OptionalProp Boolean -> Boolean
5657isTruthy = getOr false
5758
58−infixr 6 getOrFlipped as ?||
59+infixr 5 getOrFlipped as ?||
5960
6061appendIfDefined ∷ ∀ a. (Semigroup a) => a -> OptionalProp a -> a
6162appendIfDefined a undefOrA = maybe a (a <> _) (opToMaybe undefOrA)
yarn.lock+18
@@ -5595,6 +5595,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24:
55955595 dependencies:
55965596 safer-buffer ">= 2.1.2 < 3"
55975597
5598+iconv-lite@^0.5.1:
5599+ version "0.5.2"
5600+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.2.tgz#af6d628dccfb463b7364d97f715e4b74b8c8c2b8"
5601+ integrity sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==
5602+ dependencies:
5603+ safer-buffer ">= 2.1.2 < 3"
5604+
55985605icss-utils@^4.0.0, icss-utils@^4.1.1:
55995606 version "4.1.1"
56005607 resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467"
@@ -8827,6 +8834,17 @@ source-list-map@^2.0.0:
88278834 resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
88288835 integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
88298836
8837+source-map-loader@^1.0.1:
8838+ version "1.0.1"
8839+ resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-1.0.1.tgz#703df5345b0816734f0336c1ccee8af66e082061"
8840+ integrity sha512-DE4CJyfCVoxFLsHyuVE9Sjcib8cs5qdmOq3wcev1Un/r6F2AfQJDhag4rzpPPA48A2QZyV3CTbc+NGoFMfKIOQ==
8841+ dependencies:
8842+ data-urls "^2.0.0"
8843+ iconv-lite "^0.5.1"
8844+ loader-utils "^2.0.0"
8845+ schema-utils "^2.6.6"
8846+ source-map "^0.6.0"
8847+
88308848source-map-resolve@^0.5.0:
88318849 version "0.5.3"
88328850 resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"