git.iko.soy/rowtype-yoga/ry-blocks
on 813237a help sign in
50 files changed+2636−2881
since splitsnapshots
unifiedsplit
.vscode/settings.json+1−1 packages.dhall+451−2 spago.dhall+1−7 src/React/Basic/Popper/Hook.js−3 src/React/Basic/Popper/Hook.purs−32 src/React/Basic/Popper/Placement/Types.purs−36 src/React/Basic/Popper/Popper.js−19 src/React/Basic/Popper/Popper.purs−17 src/React/Basic/Popper/Story.purs−242 src/React/Basic/Popper/Types.purs−31 src/React/Basic/SyntaxHighlighter/Component.js+148−148 src/React/DndKit.js+45−23 src/React/Downshift/Internal.js+2−2 src/React/Downshift/Types/StateChangeType.js+27−23 src/Web/DOM/ResizeObserver.js+28−28 src/Web/DOM/ResizeObserver.purs+9−9 src/Yoga.purs+29−22 src/Yoga/Block.purs−8 src/Yoga/Block/Atom/Input/Hook/UseTypingPlaceholders.purs+165 src/Yoga/Block/Atom/Input/Story.purs+34−36 src/Yoga/Block/Atom/Input/Style.purs+3−3 src/Yoga/Block/Atom/Input/View.purs+83−50 src/Yoga/Block/Atom/Input/View/Container.purs+43−40 src/Yoga/Block/Atom/Input/View/Label.purs+37−36 src/Yoga/Block/Atom/Popover.purs−5 src/Yoga/Block/Atom/Popover/Story.purs−57 src/Yoga/Block/Atom/Popover/Style.purs−129 src/Yoga/Block/Atom/Popover/View.purs−114 src/Yoga/Block/Atom/Segmented/View.purs+39−32 src/Yoga/Block/Atom/Segmented/View/ActiveIndicator.purs+3−5 src/Yoga/Block/Atom/Tooltip.purs−5 src/Yoga/Block/Atom/Tooltip/Spec.purs−16 src/Yoga/Block/Atom/Tooltip/Story.purs−39 src/Yoga/Block/Atom/Tooltip/Style.purs−58 src/Yoga/Block/Atom/Tooltip/View.purs−126 src/Yoga/Block/Container/Style.js+24−14 src/Yoga/Block/Container/Style.purs+102−102 src/Yoga/Block/Hook/Key.js+7−7 src/Yoga/Block/Hook/UseInView.js+2−2 src/Yoga/Block/Hook/UseResize.purs+10−9 src/Yoga/Block/Internal.js+53−39 src/Yoga/Block/Internal.purs+549−552 src/Yoga/Block/Internal/OptionalProp.purs+12−10 src/Yoga/Block/Molecule/Sheet/View.purs+67−63 src/Yoga/Block/Organism/Form.purs+427−426 src/Yoga/Block/Organism/Form/Internal.purs+68−66 src/Yoga/Block/Organism/Form/Story.purs+27−21 src/Yoga/Block/Organism/Form/Validation.purs+111−95 src/Yoga/Block/Palette/Story.purs+24−20 src/Yoga/Prelude/View.purs+5−51
.vscode/settings.json+1−1
@@ -1,6 +1,6 @@
11{
22 "editor.formatOnSave": true,
3− "workbench.colorTheme": "Abyss",
3+ "workbench.colorTheme": "Horizon Bright",
44 "search.useGlobalIgnoreFiles": true,
55 "files.watcherExclude": {
66 "**/.spago/**": true,
packages.dhall+451−2
@@ -99,7 +99,456 @@ in upstream
9999-------------------------------
100100-}
101101let upstream =
102− https://github.com/purescript/package-sets/releases/download/psc-0.14.2-20210629/packages.dhall
103− sha256:534c490bb73cae75adb5a39871142fd8db5c2d74c90509797a80b8bb0d5c3f7b
102+ https://raw.githubusercontent.com/purescript/package-sets/prepare-0.15/src/packages.dhall
103+ sha256:b1c6d06132b7cbf1e93b1e5343044fba1604b50bfbe02d8f80a3002e71569c59
104104
105105in upstream
106+ with framer-motion =
107+ { version = "es-modules"
108+ , repo = "https://github.com/i-am-the-slime/purescript-framer-motion.git"
109+ , dependencies =
110+ [ "aff"
111+ , "aff-promise"
112+ , "arrays"
113+ , "console"
114+ , "effect"
115+ , "foreign"
116+ , "foreign-object"
117+ , "heterogeneous"
118+ , "literals"
119+ , "maybe"
120+ , "nullable"
121+ , "prelude"
122+ , "psci-support"
123+ , "react-basic"
124+ , "react-basic-dom"
125+ , "react-basic-hooks"
126+ , "record"
127+ , "tuples"
128+ , "two-or-more"
129+ , "typelevel-prelude"
130+ , "unsafe-coerce"
131+ , "untagged-union"
132+ , "web-dom"
133+ , "web-events"
134+ , "web-uievents"
135+ ]
136+ }
137+ with spec =
138+ { repo = "https://github.com/purescript-spec/purescript-spec.git"
139+ , version = "master"
140+ , dependencies =
141+ [ "aff"
142+ , "ansi"
143+ , "avar"
144+ , "console"
145+ , "exceptions"
146+ , "foldable-traversable"
147+ , "fork"
148+ , "now"
149+ , "pipes"
150+ , "prelude"
151+ , "strings"
152+ , "transformers"
153+ ]
154+ }
155+ with spec-discovery =
156+ { repo = "https://github.com/purescript-spec/purescript-spec-discovery.git"
157+ , version = "master"
158+ , dependencies =
159+ [ "aff"
160+ , "aff-promise"
161+ , "arrays"
162+ , "console"
163+ , "effect"
164+ , "foldable-traversable"
165+ , "node-fs"
166+ , "prelude"
167+ , "spec"
168+ ]
169+ }
170+ with playwright =
171+ { repo =
172+ "https://github.com/working-group-purescript-es/purescript-playwright.git"
173+ , version = "es-modules"
174+ , dependencies =
175+ [ "argonaut-core"
176+ , "console"
177+ , "effect"
178+ , "prelude"
179+ , "psci-support"
180+ , "aff-promise"
181+ , "test-unit"
182+ , "untagged-union"
183+ , "node-buffer"
184+ , "node-fs-aff"
185+ , "undefined"
186+ , "aff"
187+ , "either"
188+ , "exceptions"
189+ , "foreign"
190+ , "foreign-object"
191+ , "literals"
192+ , "maybe"
193+ , "node-streams"
194+ , "ordered-collections"
195+ , "refs"
196+ , "strings"
197+ , "transformers"
198+ ]
199+ }
200+ with milkis =
201+ { repo =
202+ "https://github.com/working-group-purescript-es/purescript-milkis.git"
203+ , version = "es-modules"
204+ , dependencies =
205+ [ "aff-promise"
206+ , "arraybuffer-types"
207+ , "foreign-object"
208+ , "prelude"
209+ , "typelevel-prelude"
210+ ]
211+ }
212+ with debug =
213+ { dependencies = [ "prelude", "functions" ]
214+ , repo =
215+ "https://github.com/working-group-purescript-es/purescript-debug.git"
216+ , version = "es-modules"
217+ }
218+ with checked-exceptions =
219+ { dependencies = [ "prelude", "transformers", "variant" ]
220+ , repo = "https://github.com/natefaubion/purescript-checked-exceptions.git"
221+ , version = "v3.1.1"
222+ }
223+ with language-cst-parser =
224+ { dependencies =
225+ [ "arrays"
226+ , "const"
227+ , "effect"
228+ , "either"
229+ , "foldable-traversable"
230+ , "free"
231+ , "functors"
232+ , "maybe"
233+ , "numbers"
234+ , "ordered-collections"
235+ , "strings"
236+ , "transformers"
237+ , "tuples"
238+ , "typelevel-prelude"
239+ ]
240+ , repo = "https://github.com/natefaubion/purescript-language-cst-parser.git"
241+ , version = "v0.9.3"
242+ }
243+ with stringutils =
244+ { dependencies =
245+ [ "arrays"
246+ , "either"
247+ , "integers"
248+ , "maybe"
249+ , "partial"
250+ , "prelude"
251+ , "strings"
252+ ]
253+ , repo =
254+ "https://github.com/working-group-purescript-es/purescript-stringutils.git"
255+ , version = "es-modules"
256+ }
257+ with routing-duplex =
258+ { dependencies =
259+ [ "arrays"
260+ , "control"
261+ , "either"
262+ , "js-uri"
263+ , "lazy"
264+ , "numbers"
265+ , "prelude"
266+ , "profunctor"
267+ , "record"
268+ , "strings"
269+ , "typelevel-prelude"
270+ ]
271+ , repo =
272+ "https://github.com/working-group-purescript-es/purescript-routing-duplex.git"
273+ , version = "v0.15.0-update"
274+ }
275+ with web-router =
276+ { dependencies =
277+ [ "aff"
278+ , "effect"
279+ , "freet"
280+ , "indexed-monad"
281+ , "prelude"
282+ , "profunctor-lenses"
283+ , "routing"
284+ ]
285+ , repo = "https://github.com/robertdp/purescript-web-router.git"
286+ , version = "v0.3.0"
287+ }
288+ with framer-motion.version = "24dc0a89dd65458b768f3731c886f9911898788d"
289+ with visx =
290+ { repo = "https://github.com/i-am-the-slime/purescript-visx.git"
291+ , version = "es-modules"
292+ , dependencies =
293+ [ "arrays"
294+ , "console"
295+ , "datetime"
296+ , "debug"
297+ , "effect"
298+ , "either"
299+ , "foldable-traversable"
300+ , "foreign"
301+ , "foreign-object"
302+ , "functions"
303+ , "integers"
304+ , "js-date"
305+ , "justifill"
306+ , "lists"
307+ , "maybe"
308+ , "newtype"
309+ , "nullable"
310+ , "orders"
311+ , "prelude"
312+ , "psci-support"
313+ , "react-basic"
314+ , "react-basic-dom"
315+ , "react-basic-hooks"
316+ , "record"
317+ , "record-extra"
318+ , "transformers"
319+ , "tuples"
320+ , "typelevel-prelude"
321+ , "unsafe-coerce"
322+ , "untagged-union"
323+ , "web-dom"
324+ ]
325+ }
326+ with graphql-fundeps =
327+ { dependencies =
328+ [ "aff"
329+ , "affjax"
330+ , "console"
331+ , "effect"
332+ , "either"
333+ , "http-methods"
334+ , "maybe"
335+ , "media-types"
336+ , "prelude"
337+ , "psci-support"
338+ , "simple-json"
339+ , "strings"
340+ ]
341+ , repo = "https://github.com/meeshkan/purescript-graphql-fundeps.git"
342+ , version = "b83fcc13d5f9b1c28baeede35319f34084ec7f3c"
343+ }
344+ with foreign-generic =
345+ { repo =
346+ "https://github.com/working-group-purescript-es/purescript-foreign-generic.git"
347+ , version = "v0.15.0-updates"
348+ , dependencies =
349+ [ "effect"
350+ , "exceptions"
351+ , "foreign"
352+ , "foreign-object"
353+ , "identity"
354+ , "ordered-collections"
355+ , "record"
356+ ]
357+ }
358+ with heterogeneous =
359+ { dependencies =
360+ [ "either", "functors", "prelude", "record", "tuples", "variant" ]
361+ , repo = "https://github.com/natefaubion/purescript-heterogeneous.git"
362+ , version = "v0.5.1"
363+ }
364+ with interpolate =
365+ { dependencies = [ "prelude" ]
366+ , repo = "https://github.com/jordanmartinez/purescript-interpolate.git"
367+ , version = "v3.0.1"
368+ }
369+ with interpolate.version = "patch-1"
370+ with interpolate.repo
371+ = "https://github.com/i-am-the-slime/purescript-interpolate.git"
372+ with justifill =
373+ { dependencies = [ "record", "spec", "typelevel-prelude" ]
374+ , repo = "https://github.com/i-am-the-slime/purescript-justifill.git"
375+ , version = "v0.2.1"
376+ }
377+ with morello =
378+ { dependencies =
379+ [ "console", "debug", "effect", "heterogeneous", "strings", "validation" ]
380+ , repo = "https://github.com/sigma-andex/purescript-morello.git"
381+ , version = "v0.2.0"
382+ }
383+ with react-basic =
384+ { dependencies = [ "prelude", "effect", "record" ]
385+ , repo = "https://github.com/lumihq/purescript-react-basic.git"
386+ , version = "v16.0.0"
387+ }
388+ with react-basic-dom =
389+ { dependencies =
390+ [ "prelude"
391+ , "console"
392+ , "effect"
393+ , "foreign-object"
394+ , "psci-support"
395+ , "react-basic"
396+ , "unsafe-coerce"
397+ , "web-dom"
398+ , "web-events"
399+ , "web-file"
400+ , "web-html"
401+ ]
402+ , repo = "https://github.com/lumihq/purescript-react-basic-dom.git"
403+ , version = "v4.2.0"
404+ }
405+ with react-basic-emotion =
406+ { dependencies =
407+ [ "colors"
408+ , "console"
409+ , "effect"
410+ , "foreign"
411+ , "foreign-object"
412+ , "numbers"
413+ , "prelude"
414+ , "react-basic"
415+ , "react-basic-hooks"
416+ , "typelevel-prelude"
417+ , "unsafe-reference"
418+ ]
419+ , repo = "https://github.com/lumihq/purescript-react-basic-emotion.git"
420+ , version = "v6.0.0"
421+ }
422+ with uuid =
423+ { dependencies = [ "effect", "maybe", "foreign-generic", "console", "spec" ]
424+ , repo = "https://github.com/i-am-the-slime/purescript-uuid.git"
425+ , version = "patch-2"
426+ }
427+ with react-basic-hooks =
428+ { dependencies =
429+ [ "aff"
430+ , "aff-promise"
431+ , "bifunctors"
432+ , "console"
433+ , "control"
434+ , "datetime"
435+ , "effect"
436+ , "either"
437+ , "exceptions"
438+ , "foldable-traversable"
439+ , "functions"
440+ , "indexed-monad"
441+ , "integers"
442+ , "maybe"
443+ , "newtype"
444+ , "now"
445+ , "nullable"
446+ , "ordered-collections"
447+ , "prelude"
448+ , "psci-support"
449+ , "react-basic"
450+ , "refs"
451+ , "tuples"
452+ , "type-equality"
453+ , "unsafe-coerce"
454+ , "unsafe-reference"
455+ , "web-html"
456+ ]
457+ , repo = "https://github.com/spicydonuts/purescript-react-basic-hooks.git"
458+ , version = "v7.0.1"
459+ }
460+ with react-basic.repo
461+ =
462+ "https://github.com/working-group-purescript-es/purescript-react-basic.git"
463+ with react-basic.version = "es-modules"
464+ with react-basic-dom.repo
465+ =
466+ "https://github.com/working-group-purescript-es/purescript-react-basic-dom.git"
467+ with react-basic-dom.version = "es-modules"
468+ with react-basic-hooks.repo
469+ =
470+ "https://github.com/working-group-purescript-es/purescript-react-basic-hooks.git"
471+ with react-basic-hooks.version = "es-modules"
472+ with react-basic-emotion.repo
473+ =
474+ "https://github.com/working-group-purescript-es/purescript-react-basic-emotion.git"
475+ with react-basic-emotion.version = "es-modules"
476+ with literals =
477+ { dependencies =
478+ [ "assert"
479+ , "effect"
480+ , "console"
481+ , "integers"
482+ , "numbers"
483+ , "partial"
484+ , "psci-support"
485+ , "unsafe-coerce"
486+ , "typelevel-prelude"
487+ ]
488+ , repo = "https://github.com/jvliwanag/purescript-literals.git"
489+ , version = "v0.2.0"
490+ }
491+ with literals.repo
492+ =
493+ "https://github.com/working-group-purescript-es/purescript-literals.git"
494+ with literals.version = "es-modules"
495+ with untagged-union =
496+ { dependencies =
497+ [ "assert"
498+ , "console"
499+ , "effect"
500+ , "foreign"
501+ , "foreign-object"
502+ , "literals"
503+ , "maybe"
504+ , "newtype"
505+ , "psci-support"
506+ , "tuples"
507+ , "unsafe-coerce"
508+ ]
509+ , repo = "https://github.com/jvliwanag/purescript-untagged-union.git"
510+ , version = "v0.3.0"
511+ }
512+ with untagged-union.repo
513+ =
514+ "https://github.com/working-group-purescript-es/purescript-untagged-union.git"
515+ with untagged-union.version = "es-modules"
516+ with react-testing-library =
517+ { name = "react-testing-library"
518+ , dependencies = [ "react-basic", "react-basic-hooks", "react-basic-dom" ]
519+ , repo =
520+ "https://github.com/i-am-the-slime/purescript-react-testing-library.git"
521+ , version = "main"
522+ }
523+ with record-extra =
524+ { repo =
525+ "https://github.com/working-group-purescript-es/purescript-record-extra.git"
526+ , version = "v0.15.0-update"
527+ , dependencies =
528+ [ "arrays"
529+ , "console"
530+ , "effect"
531+ , "functions"
532+ , "lists"
533+ , "maybe"
534+ , "prelude"
535+ , "record"
536+ , "tuples"
537+ , "typelevel-prelude"
538+ ]
539+ }
540+ with variant =
541+ { dependencies =
542+ [ "enums"
543+ , "lists"
544+ , "maybe"
545+ , "partial"
546+ , "prelude"
547+ , "record"
548+ , "tuples"
549+ , "unsafe-coerce"
550+ ]
551+ , repo =
552+ "https://github.com/working-group-purescript-es/purescript-variant.git"
553+ , version = "v0.15.0-update"
554+ }
spago.dhall+1−7
@@ -5,7 +5,6 @@ You can edit this file as you like.
55{ name = "ry-blocks"
66, dependencies =
77 [ "aff"
8− , "aff-promise"
98 , "arrays"
109 , "colors"
1110 , "console"
@@ -26,9 +25,7 @@ You can edit this file as you like.
2625 , "heterogeneous"
2726 , "integers"
2827 , "interpolate"
29− , "lists"
3028 , "literals"
31− , "math"
3229 , "maybe"
3330 , "newtype"
3431 , "nullable"
@@ -37,7 +34,7 @@ You can edit this file as you like.
3734 , "partial"
3835 , "prelude"
3936 , "profunctor-lenses"
40− , "psci-support"
37+ , "random"
4138 , "react-basic"
4239 , "react-basic-dom"
4340 , "react-basic-emotion"
@@ -45,8 +42,6 @@ You can edit this file as you like.
4542 , "react-testing-library"
4643 , "record"
4744 , "record-extra"
48− , "routing"
49− , "routing-duplex"
5045 , "spec"
5146 , "spec-discovery"
5247 , "strings"
@@ -61,7 +56,6 @@ You can edit this file as you like.
6156 , "web-dom"
6257 , "web-events"
6358 , "web-html"
64− , "web-uievents"
6559 ]
6660, packages = ./packages.dhall
6761, sources = [ "src/**/*.purs", "test/**/*.purs" ]
src/React/Basic/Popper/Hook.jsdeleted−3
@@ -1,3 +0,0 @@
1−const reactPopper = require('react-popper')
2−
3−exports.usePopperImpl = reactPopper.usePopper
src/React/Basic/Popper/Hook.pursdeleted−32
@@ -1,32 +0,0 @@
1−module React.Basic.Popper.Hook where
2−
3−import Prelude
4−import Data.String as String
5−import Data.Tuple (Tuple(..))
6−import Effect.Uncurried (EffectFn3, runEffectFn3)
7−import Foreign.Object (Object)
8−import Foreign.Object as Object
9−import Prim.Row (class Union)
10−import Yoga.Prelude.View (Hook, unsafeHook)
11−import React.Basic.Popper.Types (Options, PopperData, PopperElement, ReferenceElement)
12−
13−foreign import data UsePopper ∷ Type -> Type -> Type
14−
15−foreign import usePopperImpl ∷ ∀ opts. EffectFn3 ReferenceElement PopperElement { | opts } PopperData
16−
17−toDataAttributes ∷ Object String -> Object String
18−toDataAttributes o = Object.toArrayWithKey (Tuple <<< dropPrefix) o # Object.fromFoldable
19− where
20− dropPrefix = String.drop (String.length "data-")
21−
22−usePopper ∷ ∀ opts opts_. Union opts opts_ Options => ReferenceElement -> PopperElement -> { | opts } -> Hook (UsePopper { | opts }) PopperData
23−usePopper elemRef popperRef opts =
24− unsafeHook do
25− result <- runEffectFn3 usePopperImpl elemRef popperRef opts
26− pure
27− $ result
28− { attributes
29− { popper = toDataAttributes result.attributes.popper
30− , arrow = toDataAttributes result.attributes.arrow
31− }
32− }
src/React/Basic/Popper/Placement/Types.pursdeleted−36
@@ -1,36 +0,0 @@
1−module React.Basic.Popper.Placement.Types (render, Placement(..), Primary(..), Secondary(..)) where
2−
3−import Prelude
4−import Data.Foldable (foldMap)
5−import Data.Maybe (Maybe)
6−
7−data Placement
8− = Placement Primary (Maybe Secondary)
9−
10−render ∷ Placement -> String
11−render (Placement primary maybeSecondary) = do
12− renderPrimary primary <> foldMap ("-" <> _) (renderSecondary <$> maybeSecondary)
13−
14−data Primary
15− = Auto
16− | Left
17− | Right
18− | Top
19− | Bottom
20−
21−data Secondary
22− = Start
23− | End
24−
25−renderPrimary ∷ Primary -> String
26−renderPrimary = case _ of
27− Auto -> "auto"
28− Left -> "left"
29− Right -> "right"
30− Top -> "top"
31− Bottom -> "bottom"
32−
33−renderSecondary ∷ Secondary -> String
34−renderSecondary = case _ of
35− Start -> "start"
36− End -> "end"
src/React/Basic/Popper/Popper.jsdeleted−19
@@ -1,19 +0,0 @@
1−exports.modifierMatchReferenceSize = {
2− name: "matchReferenceSize",
3− enabled: true,
4− fn: ({ state, instance }) => {
5− const widthOrHeight =
6− state.placement.startsWith("left") ||
7− state.placement.startsWith("right")
8− ? "height"
9− : "width";
10− const popperSize = state.rects.popper[widthOrHeight];
11− const referenceSize = state.rects.reference[widthOrHeight];
12− if (popperSize >= referenceSize) return;
13−
14− state.styles.popper[widthOrHeight] = `${referenceSize}px`;
15− instance.update();
16− },
17− phase: "beforeWrite",
18− requires: ["computeStyles"]
19−}
src/React/Basic/Popper/Popper.pursdeleted−17
@@ -1,17 +0,0 @@
1−module React.Basic.Popper where
2−
3−import Data.Nullable (null)
4−import React.Basic.Popper.Types (ArrowElement, Modifier)
5−import Unsafe.Coerce (unsafeCoerce)
6−import Yoga.Block.Internal (NodeRef)
7−
8−nullRef ∷ NodeRef
9−nullRef = unsafeCoerce null
10−
11−modifierArrow ∷ { element ∷ ArrowElement, padding ∷ Int } -> Modifier
12−modifierArrow options = unsafeCoerce { name: "arrow", options }
13−
14−modifierOffset ∷ { x ∷ Number, y ∷ Number } -> Modifier
15−modifierOffset { x, y } = unsafeCoerce { name: "offset", options: { offset: [ x, y ] } }
16−
17−foreign import modifierMatchReferenceSize ∷ Modifier
src/React/Basic/Popper/Story.pursdeleted−242
@@ -1,242 +0,0 @@
1−module React.Basic.Popper.Story where
2−
3−import Yoga.Prelude.View
4−import Data.Interpolate (i)
5−import Effect.Uncurried (mkEffectFn1)
6−import Effect.Unsafe (unsafePerformEffect)
7−import Framer.Motion as Motion
8−import React.Basic.DOM (h2_, text)
9−import React.Basic.DOM as R
10−import React.Basic.Emotion as E
11−import React.Basic.Hooks as React
12−import React.Basic.Popper.Hook (usePopper)
13−import React.Basic.Popper (modifierArrow, modifierOffset)
14−import Unsafe.Coerce (unsafeCoerce)
15−import Yoga.Block as Block
16−import Yoga.Block.Container.Style as Styles
17−import Yoga.Block.Internal.CSS (nest)
18−
19−default ∷
20− { decorators ∷ Array (Effect JSX -> JSX)
21− , title ∷ String
22− }
23−default =
24− { title: "Popper"
25− , decorators:
26− [ \storyFn ->
27− div
28− </ {}
29− /> [ element E.global { styles: Styles.global }
30− , unsafePerformEffect storyFn
31− ]
32− ]
33− }
34−
35−popper ∷ Effect JSX
36−popper = do
37− example <- mkBasicExample
38− pure
39− $ fragment
40− [ div </ {}
41− /> [ h2_ [ text "Some Popper" ]
42− , element example {}
43− ]
44− ]
45− where
46− nullRef ∷ NodeRef
47− nullRef = unsafeCoerce null
48−
49− mkBasicExample =
50− React.reactComponent "Popper example" \_p -> React.do
51− referenceElement /\ setReferenceElement <- React.useState' nullRef
52− popperElement /\ setPopperElement <- React.useState' nullRef
53− arrowElement /\ setArrowElement <- React.useState' nullRef
54− { styles, attributes } <-
55− usePopper referenceElement popperElement
56− { modifiers:
57− [ modifierArrow { element: arrowElement, padding: 4 }
58− , modifierOffset { x: 0.0, y: 8.0 }
59− ]
60− }
61− pure
62− $ fragment
63− $ [ button
64− </ { type: "button"
65− , ref: unsafeCoerce (mkEffectFn1 setReferenceElement)
66− }
67− /> [ text "Reference element" ]
68− , div
69− </* { className: "popper-element"
70− , css:
71− E.css
72− { background: E.str "darkslateblue"
73− , borderRadius: E.str "8px"
74− , display: E.str "block"
75− , padding: E.str "4px 8px"
76− , "&[data-popper-placement^='top'] > .popper-arrow":
77− nest { bottom: E.str "-4px" }
78− , "&[data-popper-placement^='bottom'] > .popper-arrow":
79− nest { top: E.str "-4px" }
80− , "&[data-popper-placement^='left'] > .popper-arrow":
81− nest { right: E.str "-4px" }
82− , "&[data-popper-placement^='right'] > .popper-arrow":
83− nest { left: E.str "-4px" }
84− }
85− , ref: unsafeCoerce (mkEffectFn1 setPopperElement)
86− , style: styles.popper
87− , _data: attributes.popper
88− }
89− /> [ text "Popper Element"
90− , div
91− </*> { className: "popper-arrow"
92− , id: "arrow"
93− , css:
94− E.css
95− { position: E.str "absolute"
96− , width: E.str "8px"
97− , height: E.str "8px"
98− , zIndex: E.str "-1"
99− , "&::before":
100− nest
101− { position: E.str "absolute"
102− , width: E.str "8px"
103− , height: E.str "8px"
104− , zIndex: E.str "-1"
105− , content: E.str "''"
106− , transform: E.str "rotate(45deg)"
107− , background: E.str "darkslateblue"
108− }
109− }
110− , ref: unsafeCoerce (mkEffectFn1 setArrowElement)
111− , style: styles.arrow
112− , _data: attributes.arrow
113− }
114− ]
115− ]
116−
117−animatedPopper ∷ Effect JSX
118−animatedPopper = do
119− example <- mkBasicExample
120− pure
121− $ fragment
122− [ R.div_
123− [ R.h2_ [ R.text "Some Popper" ]
124− , element example {}
125− ]
126− ]
127− where
128− nullRef ∷ NodeRef
129− nullRef = unsafeCoerce null
130−
131− mkBasicExample =
132− React.reactComponent "Popper example" \_p -> React.do
133− -- Hooks
134− referenceElement /\ setReferenceElement <- React.useState' nullRef
135− popperElement /\ setPopperElement <- React.useState' nullRef
136− arrowElement /\ setArrowElement <- React.useState' nullRef
137− { styles, attributes } <-
138− usePopper referenceElement popperElement
139− { modifiers:
140− [ modifierArrow { element: arrowElement, padding: 4 }
141− , modifierOffset { x: 0.0, y: 12.0 }
142− ]
143− }
144− on /\ setOn <- React.useState' true
145− -- Handlers
146− let buttonClicked = setOn (not on)
147− -- Elements
148− let
149− result =
150− fragment
151− $ [ refElem
152− , popperEl
153− [ animatePresence
154− $ guard on
155− [ content
156− [ Block.box {} [ text "Ich bin Stinky Bill" ]
157− , arrow
158− ]
159− ]
160− ]
161− ]
162− animatePresence =
163− Motion.animatePresence
164− </ { initial: false
165− }
166− content =
167− Motion.div
168− </* { className: "popper-element-content"
169− , css: contentCss
170− , initial: Motion.initial $ R.css { opacity: [ 1.0, 0.8, 0.0 ], scale: [ 1.0, 0.85 ] }
171− , animate: Motion.animate $ R.css { opacity: [ 0.0, 0.3, 1.0 ], scale: [ 0.0, 1.05, 1.0, 0.98, 1.01, 1.0 ] }
172− , exit: Motion.exit $ R.css { opacity: [ 1.0, 0.8, 0.0 ], scale: [ 1.0, 0.85 ] }
173− , transition: Motion.transition { duration: 0.2 }
174− , key: "container"
175− }
176− popperEl =
177− div
178− </* { className: "popper-element"
179− , css: popperCss
180− , ref: unsafeCoerce (mkEffectFn1 setPopperElement)
181− , style: styles.popper
182− , _data: attributes.popper
183− }
184− arrow =
185− div
186− </*> { className: "popper-arrow"
187− , id: "arrow"
188− , css: arrowCss
189− , ref: unsafeCoerce (mkEffectFn1 setArrowElement)
190− , style: styles.arrow
191− , _data: attributes.arrow
192− }
193− refElem =
194− button
195− </ { ref: unsafeCoerce (mkEffectFn1 setReferenceElement)
196− , onClick: handler preventDefault (const buttonClicked)
197− }
198− /> [ R.text "Reference element" ]
199− pure result
200−
201− backgroundColour = "var(--highlight)"
202−
203− backgroundColour2 = "rgb(100, 160, 240)"
204−
205− arrowCss =
206− E.css
207− { position: E.str "absolute"
208− , width: E.str "8px"
209− , height: E.str "8px"
210− , zIndex: E.str "0"
211− , "&::before":
212− nest
213− { position: E.str "absolute"
214− , width: E.str "8px"
215− , height: E.str "8px"
216− , content: E.str "''"
217− , transform: E.str "rotate(45deg)"
218− , background: E.str backgroundColour
219− }
220− }
221−
222− contentCss =
223− E.css
224− { background: E.str $ i "linear-gradient(0deg," backgroundColour "," backgroundColour2 "," backgroundColour ")"
225− , fontSize: E.str "14px"
226− , zIndex: E.str "-1"
227− , color: E.str $ "white"
228− , boxShadow: E.str "0 1px 8px rgba(0,0,0,0.5)"
229− , borderRadius: E.str "12px"
230− }
231−
232− popperCss =
233− E.css
234− { "&[data-popper-placement^='top'] > * > .popper-arrow":
235− nest { bottom: E.str "-4px" }
236− , "&[data-popper-placement^='bottom'] > * > .popper-arrow":
237− nest { top: E.str "-4px" }
238− , "&[data-popper-placement^='left'] > * > .popper-arrow":
239− nest { right: E.str "-4px" }
240− , "&[data-popper-placement^='right'] > * > .popper-arrow":
241− nest { left: E.str "-4px" }
242− }
src/React/Basic/Popper/Types.pursdeleted−31
@@ -1,31 +0,0 @@
1−module React.Basic.Popper.Types where
2−
3−import Foreign.Object (Object)
4−import React.Basic.DOM (CSS)
5−import Yoga.Prelude.View (NodeRef)
6−
7−type ReferenceElement =
8− NodeRef
9−
10−type PopperElement =
11− NodeRef
12−
13−type ArrowElement =
14− NodeRef
15−
16−type DataAttributes =
17− { popper ∷ Object String, arrow ∷ Object String }
18−
19−type Styles =
20− { popper ∷ CSS, arrow ∷ CSS }
21−
22−type PopperData =
23− { styles ∷ Styles, attributes ∷ DataAttributes }
24−
25−foreign import data Modifier ∷ Type
26−
27−type Options =
28− ( modifiers ∷ Array Modifier
29− , strategy ∷ String
30− , placement ∷ String
31− )
src/React/Basic/SyntaxHighlighter/Component.js+148−148
@@ -1,149 +1,149 @@
1−"use strict";
2−Object.defineProperty(exports, "__esModule", { value: true });
3−var react_syntax_highlighter_1 = require("react-syntax-highlighter");
1+"use strict"
2+import { Light } from "react-syntax-highlighter"
43var purescript = function (hljs) {
5− var COMMENT = {
6− variants: [
7− hljs.COMMENT("--", "$"),
8− hljs.COMMENT("{-", "-}", {
9− contains: ["self"],
10− }),
11− ],
12− };
13− var ESCAPED_KEY = {
14− className: "attribute",
15− begin: '"',
16− illegal: '"',
17− end: '"',
18− relevance: 0,
19− };
20− // var KEY = {
21− // className: "attribute",
22− // begin: "[a-z]",
23− // illegal: ""
24− // end: "(::|∷)",
25− // excludeEnd: true,
26− // relevance: 0,
27− // };
28− var CONSTRUCTOR = {
29− className: "type",
30− begin: "\\b[A-Z][\\w']*",
31− relevance: 0,
32− };
33− var LIST = {
34− begin: "\\(",
35− end: "\\)",
36− illegal: '"',
37− contains: [
38− { className: "type", begin: "\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?" },
39− hljs.inherit(hljs.TITLE_MODE, { begin: "[_a-z][\\w']*" }),
40− COMMENT,
41− ],
42− };
43− var VALUE = {};
44− var KEY_VALUE = {
45− className: "attribute",
46− begin: "\\w+",
47− end: ",|}",
48− contains: [VALUE],
49− };
50− var RECORD = {
51− begin: "{",
52− end: "}",
53− contains: [KEY_VALUE],
54− };
55− return {
56− name: "PureScript",
57− aliases: ["purs", "purescript"],
58− keywords: {
59− keyword: "case " +
60− "class " +
61− "data " +
62− "derive " +
63− "ado " +
64− "do " +
65− "else " +
66− "if " +
67− "import " +
68− "in " +
69− "infix " +
70− "infixl " +
71− "infixr " +
72− "instance " +
73− "let " +
74− "module " +
75− "newtype " +
76− "of " +
77− "then " +
78− "type " +
79− "where " +
80− ": " +
81− "foreign " +
82− "forall " +
83− "∀",
84− },
85− contains: [
86− // Top-level constructions.
87− {
88− beginKeywords: "module",
89− end: "where",
90− keywords: "module where",
91− contains: [LIST, COMMENT],
92− illegal: "\\W\\.|;",
93− },
94− {
95− begin: "\\bimport\\b",
96− end: "$",
97− keywords: "import as hiding",
98− contains: [LIST, COMMENT],
99− illegal: "\\W\\.|;",
100− },
101− {
102− className: "class",
103− begin: "^(\\s*)?(class|instance)\\b",
104− end: "where",
105− keywords: "class instance where",
106− contains: [CONSTRUCTOR, LIST, COMMENT],
107− },
108− {
109− className: "class",
110− begin: "\\b(data|(new)?type)\\b",
111− end: "$",
112− keywords: "data family type newtype derive",
113− contains: [CONSTRUCTOR, LIST, RECORD, COMMENT],
114− },
115− {
116− className: "symbol",
117− begin: "=|<-|->|\\:\\:|\\\\|=>|<=|forall|∀|\\:|∷|{|}|\\(|\\)|\\[|\\]|,",
118− invalid: "/",
119− },
120− {
121− beginKeywords: "default",
122− end: "$",
123− contains: [CONSTRUCTOR, LIST, COMMENT],
124− },
125− {
126− beginKeywords: "infix infixl infixr",
127− end: "$",
128− contains: [hljs.C_NUMBER_MODE, COMMENT],
129− },
130− {
131− begin: "\\bforeign\\b",
132− end: "$",
133− keywords: "foreign import",
134− contains: [CONSTRUCTOR, hljs.QUOTE_STRING_MODE, COMMENT],
135− },
136− // "Whitespaces".
137− // Literals and names.
138− // TODO: characters.
139− hljs.QUOTE_STRING_MODE,
140− hljs.C_NUMBER_MODE,
141− CONSTRUCTOR,
142− hljs.inherit(hljs.TITLE_MODE, { begin: "^[_a-z][\\w']*" }),
143− COMMENT,
144− { begin: "->|<-" },
145− ],
146− };
147−};
148−react_syntax_highlighter_1.Light.registerLanguage("puresscript", purescript);
149−exports.syntaxHighlighter = react_syntax_highlighter_1.Light;
4+ var COMMENT = {
5+ variants: [
6+ hljs.COMMENT("--", "$"),
7+ hljs.COMMENT("{-", "-}", {
8+ contains: ["self"]
9+ })
10+ ]
11+ }
12+ var ESCAPED_KEY = {
13+ className: "attribute",
14+ begin: '"',
15+ illegal: '"',
16+ end: '"',
17+ relevance: 0
18+ }
19+ // var KEY = {
20+ // className: "attribute",
21+ // begin: "[a-z]",
22+ // illegal: ""
23+ // end: "(::|∷)",
24+ // excludeEnd: true,
25+ // relevance: 0,
26+ // };
27+ var CONSTRUCTOR = {
28+ className: "type",
29+ begin: "\\b[A-Z][\\w']*",
30+ relevance: 0
31+ }
32+ var LIST = {
33+ begin: "\\(",
34+ end: "\\)",
35+ illegal: '"',
36+ contains: [
37+ { className: "type", begin: "\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?" },
38+ hljs.inherit(hljs.TITLE_MODE, { begin: "[_a-z][\\w']*" }),
39+ COMMENT
40+ ]
41+ }
42+ var VALUE = {}
43+ var KEY_VALUE = {
44+ className: "attribute",
45+ begin: "\\w+",
46+ end: ",|}",
47+ contains: [VALUE]
48+ }
49+ var RECORD = {
50+ begin: "{",
51+ end: "}",
52+ contains: [KEY_VALUE]
53+ }
54+ return {
55+ name: "PureScript",
56+ aliases: ["purs", "purescript"],
57+ keywords: {
58+ keyword:
59+ "case " +
60+ "class " +
61+ "data " +
62+ "derive " +
63+ "ado " +
64+ "do " +
65+ "else " +
66+ "if " +
67+ "import " +
68+ "in " +
69+ "infix " +
70+ "infixl " +
71+ "infixr " +
72+ "instance " +
73+ "let " +
74+ "module " +
75+ "newtype " +
76+ "of " +
77+ "then " +
78+ "type " +
79+ "where " +
80+ ": " +
81+ "foreign " +
82+ "forall " +
83+ "∀"
84+ },
85+ contains: [
86+ // Top-level constructions.
87+ {
88+ beginKeywords: "module",
89+ end: "where",
90+ keywords: "module where",
91+ contains: [LIST, COMMENT],
92+ illegal: "\\W\\.|;"
93+ },
94+ {
95+ begin: "\\bimport\\b",
96+ end: "$",
97+ keywords: "import as hiding",
98+ contains: [LIST, COMMENT],
99+ illegal: "\\W\\.|;"
100+ },
101+ {
102+ className: "class",
103+ begin: "^(\\s*)?(class|instance)\\b",
104+ end: "where",
105+ keywords: "class instance where",
106+ contains: [CONSTRUCTOR, LIST, COMMENT]
107+ },
108+ {
109+ className: "class",
110+ begin: "\\b(data|(new)?type)\\b",
111+ end: "$",
112+ keywords: "data family type newtype derive",
113+ contains: [CONSTRUCTOR, LIST, RECORD, COMMENT]
114+ },
115+ {
116+ className: "symbol",
117+ begin: "=|<-|->|\\:\\:|\\\\|=>|<=|forall|∀|\\:|∷|{|}|\\(|\\)|\\[|\\]|,",
118+ invalid: "/"
119+ },
120+ {
121+ beginKeywords: "default",
122+ end: "$",
123+ contains: [CONSTRUCTOR, LIST, COMMENT]
124+ },
125+ {
126+ beginKeywords: "infix infixl infixr",
127+ end: "$",
128+ contains: [hljs.C_NUMBER_MODE, COMMENT]
129+ },
130+ {
131+ begin: "\\bforeign\\b",
132+ end: "$",
133+ keywords: "foreign import",
134+ contains: [CONSTRUCTOR, hljs.QUOTE_STRING_MODE, COMMENT]
135+ },
136+ // "Whitespaces".
137+ // Literals and names.
138+ // TODO: characters.
139+ hljs.QUOTE_STRING_MODE,
140+ hljs.C_NUMBER_MODE,
141+ CONSTRUCTOR,
142+ hljs.inherit(hljs.TITLE_MODE, { begin: "^[_a-z][\\w']*" }),
143+ COMMENT,
144+ { begin: "->|<-" }
145+ ]
146+ }
147+}
148+Light.registerLanguage("puresscript", purescript)
149+export const syntaxHighlighter = Light
src/React/DndKit.js+45−23
@@ -1,23 +1,45 @@
1−const dndKitCore = require('@dnd-kit/core')
2−const dndKitSortable = require('@dnd-kit/sortable')
3−const dndKitModifiers = require('@dnd-kit/modifiers')
4−const dndKitUtilities = require('@dnd-kit/utilities')
5−exports.dndContextImpl = dndKitCore.DndContext
6−exports.closestCenter = dndKitCore.closestCenter
7−exports.closestCorners = dndKitCore.closestCorners
8−exports.sortableContextImpl = dndKitSortable.SortableContext
9−exports.useSortableImpl = dndKitSortable.useSortable
10−exports.arrayMoveImpl = dndKitSortable.arrayMove
11−exports.restrictToHorizontalAxis = dndKitModifiers.restrictToHorizontalAxis
12−exports.restrictToVerticalAxis = dndKitModifiers.restrictToVerticalAxis
13−exports.restrictToParentElement = dndKitModifiers.restrictToParentElement
14−exports.restrictToFirstScrollableAncestor =
15− dndKitModifiers.restrictToFirstScrollableAncestor
16−exports.restrictToWindowEdges = dndKitModifiers.restrictToWindowEdges
17−exports.cssToString = dndKitUtilities.CSS.Transform.toString
18−exports.keyboardSensor = dndKitCore.KeyboardSensor
19−exports.pointerSensor = dndKitCore.PointerSensor
20−exports.useSensorImpl = dndKitCore.useSensor
21−exports.useSensorsImpl = (args) => dndKitCore.useSensors.apply(args)
22−exports.sortableKeyboardCoordinates = dndKitSortable.sortableKeyboardCoordinates
23−exports.verticalListSortingStrategy = dndKitSortable.verticalListSortingStrategy
1+import {
2+ DndContext,
3+ closestCenter as closestCenter_,
4+ closestCorners as closestCorners_,
5+ KeyboardSensor,
6+ PointerSensor,
7+ useSensor,
8+ useSensors
9+} from "@dnd-kit/core"
10+import {
11+ SortableContext,
12+ useSortable,
13+ arrayMove,
14+ sortableKeyboardCoordinates as sortableKeyboardCoordinates_,
15+ verticalListSortingStrategy as verticalListSortingStrategy_
16+} from "@dnd-kit/sortable"
17+import {
18+ restrictToHorizontalAxis as restrictToHorizontalAxis_,
19+ restrictToVerticalAxis as restrictToVerticalAxis_,
20+ restrictToParentElement as restrictToParentElement_,
21+ restrictToFirstScrollableAncestor as restrictToFirstScrollableAncestor_,
22+ restrictToWindowEdges as restrictToWindowEdges_
23+} from "@dnd-kit/modifiers"
24+import { CSS } from "@dnd-kit/utilities"
25+export const dndContextImpl = DndContext
26+export const closestCenter = closestCenter_
27+export const closestCorners = closestCorners_
28+export const sortableContextImpl = SortableContext
29+export const useSortableImpl = useSortable
30+export const arrayMoveImpl = arrayMove
31+export const restrictToHorizontalAxis = restrictToHorizontalAxis_
32+export const restrictToVerticalAxis = restrictToVerticalAxis_
33+export const restrictToParentElement = restrictToParentElement_
34+export const restrictToFirstScrollableAncestor =
35+ restrictToFirstScrollableAncestor_
36+export const restrictToWindowEdges = restrictToWindowEdges_
37+export const cssToString = CSS.Transform.toString
38+export const keyboardSensor = KeyboardSensor
39+export const pointerSensor = PointerSensor
40+export const useSensorImpl = useSensor
41+export function useSensorsImpl(args) {
42+ return useSensors.apply(args)
43+}
44+export const sortableKeyboardCoordinates = sortableKeyboardCoordinates_
45+export const verticalListSortingStrategy = verticalListSortingStrategy_
src/React/Downshift/Internal.js+2−2
@@ -1,2 +1,2 @@
1−const downshift = require("downshift")
2−exports.useSelectImpl = downshift.useSelect
1+import { useSelect } from "downshift"
2+export const useSelectImpl = useSelect
src/React/Downshift/Types/StateChangeType.js+27−23
@@ -1,25 +1,29 @@
11const stateChangeTypes = require("downshift").useSelect.stateChangeTypes
22
3−exports.menuKeyDownArrowDown = stateChangeTypes.MenuKeyDownArrowDown
4−exports.menuKeyDownArrowUp = stateChangeTypes.MenuKeyDownArrowUp
5−exports.menuKeyDownEscape = stateChangeTypes.MenuKeyDownEscape
6−exports.menuKeyDownHome = stateChangeTypes.MenuKeyDownHome
7−exports.menuKeyDownEnd = stateChangeTypes.MenuKeyDownEnd
8−exports.menuKeyDownEnter = stateChangeTypes.MenuKeyDownEnter
9−exports.menuKeyDownSpaceButton = stateChangeTypes.MenuKeyDownSpaceButton
10−exports.menuKeyDownCharacter = stateChangeTypes.MenuKeyDownCharacter
11−exports.menuBlur = stateChangeTypes.MenuBlur
12−exports.menuMouseLeave = stateChangeTypes.MenuMouseLeave
13−exports.itemMouseMove = stateChangeTypes.ItemMouseMove
14−exports.itemClick = stateChangeTypes.ItemClick
15−exports.toggleButtonClick = stateChangeTypes.ToggleButtonClick
16−exports.toggleButtonKeyDownCharacter = stateChangeTypes.ToggleButtonKeyDownCharacter
17−exports.toggleButtonKeyDownArrowDown = stateChangeTypes.ToggleButtonKeyDownArrowDown
18−exports.toggleButtonKeyDownArrowUp = stateChangeTypes.ToggleButtonKeyDownArrowUp
19−exports.functionToggleMenu = stateChangeTypes.FunctionToggleMenu
20−exports.functionOpenMenu = stateChangeTypes.FunctionOpenMenu
21−exports.functionCloseMenu = stateChangeTypes.FunctionCloseMenu
22−exports.functionSetHighlightedIndex = stateChangeTypes.FunctionSetHighlightedIndex
23−exports.functionSelectItem = stateChangeTypes.FunctionSelectItem
24−exports.functionSetInputValue = stateChangeTypes.FunctionSetInputValue
25−exports.functionReset = stateChangeTypes.FunctionReset
3+export const menuKeyDownArrowDown = stateChangeTypes.MenuKeyDownArrowDown
4+export const menuKeyDownArrowUp = stateChangeTypes.MenuKeyDownArrowUp
5+export const menuKeyDownEscape = stateChangeTypes.MenuKeyDownEscape
6+export const menuKeyDownHome = stateChangeTypes.MenuKeyDownHome
7+export const menuKeyDownEnd = stateChangeTypes.MenuKeyDownEnd
8+export const menuKeyDownEnter = stateChangeTypes.MenuKeyDownEnter
9+export const menuKeyDownSpaceButton = stateChangeTypes.MenuKeyDownSpaceButton
10+export const menuKeyDownCharacter = stateChangeTypes.MenuKeyDownCharacter
11+export const menuBlur = stateChangeTypes.MenuBlur
12+export const menuMouseLeave = stateChangeTypes.MenuMouseLeave
13+export const itemMouseMove = stateChangeTypes.ItemMouseMove
14+export const itemClick = stateChangeTypes.ItemClick
15+export const toggleButtonClick = stateChangeTypes.ToggleButtonClick
16+export const toggleButtonKeyDownCharacter =
17+ stateChangeTypes.ToggleButtonKeyDownCharacter
18+export const toggleButtonKeyDownArrowDown =
19+ stateChangeTypes.ToggleButtonKeyDownArrowDown
20+export const toggleButtonKeyDownArrowUp =
21+ stateChangeTypes.ToggleButtonKeyDownArrowUp
22+export const functionToggleMenu = stateChangeTypes.FunctionToggleMenu
23+export const functionOpenMenu = stateChangeTypes.FunctionOpenMenu
24+export const functionCloseMenu = stateChangeTypes.FunctionCloseMenu
25+export const functionSetHighlightedIndex =
26+ stateChangeTypes.FunctionSetHighlightedIndex
27+export const functionSelectItem = stateChangeTypes.FunctionSelectItem
28+export const functionSetInputValue = stateChangeTypes.FunctionSetInputValue
29+export const functionReset = stateChangeTypes.FunctionReset
src/Web/DOM/ResizeObserver.js+28−28
@@ -1,33 +1,33 @@
1−"use strict";
1+"use strict"
22
3−exports.resizeObserver = function (cb) {
4− return function () {
5− return new ResizeObserver(function (entries, observer) {
6− return cb(entries)(observer)();
7− });
8− };
9−};
10−
11−exports._observe = function (element) {
12− return function (config) {
13− return function (observer) {
14− return function () {
15− return observer.observe(element, config);
16− };
17− };
18− };
19−};
3+export function resizeObserver(cb) {
4+ return function () {
5+ return new ResizeObserver(function (entries, observer) {
6+ return cb(entries)(observer)()
7+ })
8+ }
9+}
2010
21−exports.unobserve = function (element) {
11+export function _observe(element) {
12+ return function (config) {
2213 return function (observer) {
23− return function () {
24− return observer.unobserve(element);
25− };
26− };
27−};
14+ return function () {
15+ return observer.observe(element, config)
16+ }
17+ }
18+ }
19+}
2820
29−exports.disconnect = function (observer) {
21+export function unobserve(element) {
22+ return function (observer) {
3023 return function () {
31− return observer.disconnect();
32− };
33−};
24+ return observer.unobserve(element)
25+ }
26+ }
27+}
28+
29+export function disconnect(observer) {
30+ return function () {
31+ return observer.disconnect()
32+ }
33+}
src/Web/DOM/ResizeObserver.purs+9−9
@@ -15,7 +15,7 @@ module Web.DOM.ResizeObserver
1515import Prelude
1616import Effect (Effect)
1717import Web.DOM (Element)
18−import Web.HTML.HTMLElement (DOMRect)
18+import Web.DOM.Element (DOMRect)
1919
2020foreign import data ResizeObserver ∷ Type
2121
@@ -44,17 +44,17 @@ optionsToFFI ContentBox = "content-box"
4444
4545optionsToFFI DevicePixelContentBox = "device-pixel-content-box"
4646
47−foreign import resizeObserver ∷
48− (Array ResizeObserverEntry -> ResizeObserver -> Effect Unit) ->
49− Effect ResizeObserver
47+foreign import resizeObserver
48+ ∷ (Array ResizeObserverEntry -> ResizeObserver -> Effect Unit)
49+ -> Effect ResizeObserver
5050
5151foreign import _observe ∷ ∀ r. Element -> Record r -> ResizeObserver -> Effect Unit
5252
53−observe ∷
54− Element ->
55− ResizeObserverBoxOptions ->
56− ResizeObserver ->
57− Effect Unit
53+observe
54+ ∷ Element
55+ -> ResizeObserverBoxOptions
56+ -> ResizeObserver
57+ -> Effect Unit
5858observe element options = _observe element { box: optionsToFFI options }
5959
6060foreign import unobserve ∷ Element -> ResizeObserver -> Effect Unit
src/Yoga.purs+29−22
@@ -1,7 +1,6 @@
11module Yoga where
22
33import Data.Function as DF
4−import Data.Symbol (SProxy(..))
54import Prim.Row (class Lacks, class Union)
65import React.Basic.DOM (Props_div, Props_span, Props_button)
76import React.Basic.DOM as R
@@ -9,6 +8,7 @@ import React.Basic.Emotion as Emotion
98import React.Basic.Hooks (JSX, ReactComponent)
109import React.Basic.Hooks as Hooks
1110import Record as Record
11+import Type.Proxy (Proxy(..))
1212import Unsafe.Coerce (unsafeCoerce)
1313
1414div ∷ ∀ attrs attrs_. Union attrs attrs_ Props_div ⇒ ReactComponent (Record attrs)
@@ -20,43 +20,50 @@ span = R.span'
2020button ∷ ∀ attrs attrs_. Union attrs attrs_ Props_button ⇒ ReactComponent (Record attrs)
2121button = R.button'
2222
23−el ∷
24− ∀ props.
25− Lacks "children" props ⇒
26− ReactComponent { children ∷ Array JSX | props } →
27− Record props → Array JSX → JSX
23+el
24+ ∷ ∀ props
25+ . Lacks "children" props
26+ ⇒ ReactComponent { children ∷ Array JSX | props }
27+ → Record props
28+ → Array JSX
29+ → JSX
2830el x props children =
2931 (Hooks.element)
30− x (Record.insert (SProxy ∷ SProxy "children") children props)
32+ x
33+ (Record.insert (Proxy ∷ Proxy "children") children props)
3134
3235infixl 5 el as </
3336
3437infixr 0 DF.apply as />
3538
36−leaf ∷
37− ∀ props.
38− Lacks "children" props ⇒
39− ReactComponent { | props } →
40− Record props → JSX
39+leaf
40+ ∷ ∀ props
41+ . Lacks "children" props
42+ ⇒ ReactComponent { | props }
43+ → Record props
44+ → JSX
4145leaf x props = Hooks.element x props
4246
4347infixl 5 leaf as </>
4448
45−styled ∷
46− ∀ props.
47− Lacks "children" props ⇒
48− ReactComponent { children ∷ Array JSX | props } →
49− { css ∷ Emotion.Style | props } → Array JSX → JSX
49+styled
50+ ∷ ∀ props
51+ . Lacks "children" props
52+ ⇒ ReactComponent { children ∷ Array JSX | props }
53+ → { css ∷ Emotion.Style | props }
54+ → Array JSX
55+ → JSX
5056styled x props children =
5157 (unsafeCoerce Emotion.element ∷ ∀ r. ReactComponent { | r } → { css ∷ Emotion.Style | r } → JSX) x
52− (Record.insert (SProxy ∷ SProxy "children") children props)
58+ (Record.insert (Proxy ∷ Proxy "children") children props)
5359
5460infixl 5 styled as </*
5561
56−styledLeaf ∷
57− ∀ props.
58− ReactComponent { className ∷ String | props } →
59− { className ∷ String, css ∷ Emotion.Style | props } → JSX
62+styledLeaf
63+ ∷ ∀ props
64+ . ReactComponent { className ∷ String | props }
65+ → { className ∷ String, css ∷ Emotion.Style | props }
66+ → JSX
6067styledLeaf = Emotion.element
6168
6269infixl 5 styledLeaf as </*>
src/Yoga/Block.purs−8
@@ -6,11 +6,9 @@ import Yoga (el, leaf)
66import Yoga.Block.Atom.Button as Button
77import Yoga.Block.Atom.Icon as Icon
88import Yoga.Block.Atom.Input as Input
9−import Yoga.Block.Atom.Popover as Popover
109import Yoga.Block.Atom.Range as Range
1110import Yoga.Block.Atom.Segmented as Segmented
1211import Yoga.Block.Atom.Toggle as Toggle
13−import Yoga.Block.Atom.Tooltip as Tooltip
1412import Yoga.Block.Container as Container
1513import Yoga.Block.Layout.Box as Box
1614import Yoga.Block.Layout.Centre as Centre
@@ -90,9 +88,6 @@ input = Input.component
9088imposter ∷ ∀ p q. Union p q Imposter.Props ⇒ ReactComponent { | p }
9189imposter = Imposter.component
9290
93−popover ∷ ∀ p p_. Union p p_ Popover.Props ⇒ ReactComponent { | Popover.MandatoryProps p }
94−popover = Popover.component
95−
9691modal ∷ ReactComponent Modal.Props
9792modal = Modal.component
9893
@@ -129,8 +124,5 @@ switcher = Switcher.component
129124toggle ∷ ∀ p q. Union p q Toggle.Props ⇒ ReactComponent { | p }
130125toggle = Toggle.component
131126
132−tooltip ∷ ∀ p q. Union p q Tooltip.Props ⇒ ReactComponent { | Tooltip.MandatoryProps p }
133−tooltip = Tooltip.component
134−
135127readMore ∷ ∀ p q. Union p q ReadMore.Props ⇒ ReactComponent (Record p)
136128readMore = ReadMore.component
src/Yoga/Block/Atom/Input/Hook/UseTypingPlaceholders.pursnew file+165
@@ -0,0 +1,165 @@
1+module Yoga.Block.Atom.Input.Hook.UseTypingPlaceholders where
2+
3+import Yoga.Prelude.View hiding (focus)
4+
5+import Data.Array.NonEmpty ((!!))
6+import Data.Array.NonEmpty as NEA
7+import Data.Newtype (class Newtype)
8+import Data.String as String
9+import Data.Traversable (for)
10+import Effect.Aff (Fiber, Milliseconds(..), delay, killFiber, launchAff, launchAff_)
11+import Effect.Aff as Aff
12+import Effect.Random (randomRange)
13+import Partial.Unsafe (unsafeCrashWith)
14+import React.Basic.Hooks as React
15+import Web.DOM.Node as Node
16+import Web.Event.Event (EventType(..))
17+import Web.Event.EventTarget (addEventListener, eventListener, removeEventListener)
18+import Web.HTML.HTMLInputElement as HTMLInputElement
19+import Yoga.Prelude.View (null) as Nullable
20+
21+newtype UseTypingPlaceholders hooks = UseTypingPlaceholders
22+ ( UseEffect Unit -- (UnsafeRefEq NodeRef)
23+ ( UseRef (Maybe (Fiber Unit))
24+ (UseRef Boolean (UseRef Int (UseRef (Nullable Node) hooks)))
25+ )
26+ )
27+
28+derive instance Newtype (UseTypingPlaceholders hooks) _
29+
30+useTypingPlaceholders
31+ ∷ String → Array String → Hook UseTypingPlaceholders NodeRef
32+useTypingPlaceholders defaultPlaceholder otherPlaceholders = coerceHook React.do
33+ let placeholders = NEA.cons' defaultPlaceholder otherPlaceholders
34+ inputRef ← React.useRef Nullable.null
35+ placeholderIndexRef ← React.useRef 0
36+ isDeletingRef ← React.useRef false
37+ fiberRef ← React.useRef Nothing
38+ let
39+ getInputValue ∷ Effect (Maybe String)
40+ getInputValue = runMaybeT do
41+ node ← readRefMaybe inputRef # MaybeT
42+ inputElement ← HTMLInputElement.fromNode node # pure # MaybeT
43+ HTMLInputElement.value inputElement <#> pure # MaybeT
44+
45+ useEffectOnce do
46+ let
47+ start = do
48+ fiber ← launchAff go
49+ writeRef fiberRef $ Just fiber
50+
51+ cancel why = do
52+ fiberʔ ← readRef fiberRef
53+ launchAff_ $ for_ fiberʔ \fib → do
54+ killFiber (Aff.error why) fib
55+ writeRef fiberRef Nothing
56+
57+ getPlaceholder = do
58+ inputElementʔ ← readRefMaybe inputRef # liftEffect <#>
59+ (_ >>= HTMLInputElement.fromNode)
60+ placeholder ← for inputElementʔ \inputElement → do
61+ HTMLInputElement.placeholder inputElement # liftEffect
62+ pure (placeholder # fromMaybe "")
63+
64+ setPlaceholder s = do
65+ inputElementʔ ← readRefMaybe inputRef # liftEffect <#>
66+ (_ >>= HTMLInputElement.fromNode)
67+ for_ inputElementʔ \inputElement → do
68+ HTMLInputElement.setPlaceholder s inputElement # liftEffect
69+
70+ mkOnFocusListener =
71+ eventListener \_ → do
72+ setPlaceholder defaultPlaceholder
73+ writeRef placeholderIndexRef 0
74+ writeRef isDeletingRef false
75+ inputValueʔ ← getInputValue
76+ when (inputValueʔ == Just "") start
77+
78+ mkOnBlurListener =
79+ eventListener \_ → do
80+ setPlaceholder ""
81+ cancel "blur"
82+
83+ mkOnInputListener =
84+ eventListener \_ → do
85+ inputValueʔ ← getInputValue
86+ if inputValueʔ /= Just "" && inputValueʔ /= Nothing then do
87+ cancel "on change non-empty"
88+ else do
89+ setPlaceholder ""
90+ writeRef placeholderIndexRef 0
91+ writeRef isDeletingRef false
92+ start
93+
94+ register et listener = do
95+ maybeInputNode ← readRefMaybe inputRef
96+ for_ maybeInputNode \ie →
97+ addEventListener et listener false (Node.toEventTarget ie)
98+
99+ unregister et listener = do
100+ maybeInputNode ← readRefMaybe inputRef
101+ for_ maybeInputNode \ie →
102+ removeEventListener et listener false (Node.toEventTarget ie)
103+
104+ go = do
105+ placeholderIndex ← readRef placeholderIndexRef # liftEffect
106+ isDeleting ← readRef isDeletingRef # liftEffect
107+ for_ (placeholders !! placeholderIndex) \toWrite → do
108+ placeholder ← getPlaceholder
109+ if not isDeleting && placeholder == toWrite then do
110+ writeRef isDeletingRef true # liftEffect
111+ delay (1200.0 # Milliseconds)
112+ setPlaceholder
113+ (String.take (String.length toWrite - 1) placeholder) #
114+ liftEffect
115+ go
116+ else if isDeleting && placeholder == "" then do
117+ writeRef isDeletingRef false # liftEffect
118+ let
119+ newPlaceholderIndex =
120+ ( (placeholderIndex + 1) `mod` (NEA.length placeholders)
121+ )
122+ writeRef placeholderIndexRef newPlaceholderIndex # liftEffect
123+ let
124+ newToWrite = placeholders !! newPlaceholderIndex # fromMaybe'
125+ \_ → unsafeCrashWith "Nope"
126+ delay (60.0 # Milliseconds)
127+ setPlaceholder (String.take 1 newToWrite) # liftEffect
128+ go
129+ else if not isDeleting then do -- We're still writing
130+ let charactersWritten = String.length placeholder
131+ delayBy1 ← randomRange 40.0 100.0 # liftEffect
132+ delayBy2 ← randomRange 40.0 100.0 # liftEffect
133+ delay (min delayBy1 delayBy2 # Milliseconds)
134+ setPlaceholder
135+ (String.take (charactersWritten + 1) toWrite) # liftEffect
136+ go
137+ else do -- We're still deleting
138+ let charactersWritten = String.length placeholder
139+ let charactersDeleted = String.length toWrite - charactersWritten
140+ case charactersDeleted of
141+ 1 → delay (100.0 # Milliseconds)
142+ 2 → delay (100.0 # Milliseconds)
143+ 3 → delay (100.0 # Milliseconds)
144+ c | c < 5 → delay (16.0 # Milliseconds)
145+ _ → delay (8.0 # Milliseconds)
146+ setPlaceholder (String.take (charactersWritten - 1) toWrite) #
147+ liftEffect
148+ go
149+ onFocusListener ← mkOnFocusListener
150+ onBlurListener ← mkOnBlurListener
151+ onInputListener ← mkOnInputListener
152+ launchAff_ do
153+ -- Avoid messing with React
154+ delay (0.0 # Milliseconds)
155+ liftEffect do
156+ register (EventType "focus") onFocusListener
157+ register (EventType "blur") onBlurListener
158+ register (EventType "input") onInputListener
159+ setPlaceholder defaultPlaceholder
160+ pure do
161+ cancel "Killed fiber because component was unmounted"
162+ unregister (EventType "focus") onFocusListener
163+ unregister (EventType "blur") onBlurListener
164+ unregister (EventType "input") onInputListener
165+ pure inputRef
src/Yoga/Block/Atom/Input/Story.purs+34−36
@@ -3,7 +3,6 @@ module Yoga.Block.Atom.Input.Story where
33import Prelude
44import Data.Foldable (traverse_)
55import Data.String.NonEmpty.Internal (NonEmptyString(..), nes)
6−import Data.Symbol (SProxy(..))
76import Effect (Effect)
87import Effect.Unsafe (unsafePerformEffect)
98import Foreign.Object as Object
@@ -23,19 +22,19 @@ import Yoga.Block.Atom.Input.View (passwordIcon)
2322import Yoga.Block.Container.Style (colour)
2423import Yoga.Block.Container.Style as Styles
2524
26−default ∷
27− { decorators ∷ Array (Effect JSX -> JSX)
28− , title ∷ String
29− }
25+default
26+ ∷ { decorators ∷ Array (Effect JSX -> JSX)
27+ , title ∷ String
28+ }
3029default =
3130 { title: "Atom/Input"
3231 , decorators:
33− [ \storyFn ->
34− R.div_
35− [ element E.global { styles: Styles.global }
36− , unsafePerformEffect storyFn
37− ]
38− ]
32+ [ \storyFn ->
33+ R.div_
34+ [ element E.global { styles: Styles.global }
35+ , unsafePerformEffect storyFn
36+ ]
37+ ]
3938 }
4039
4140input ∷ Effect JSX
@@ -46,17 +45,17 @@ input = do
4645 [ R.h1_ [ R.text "Input Examples" ]
4746 , R.h3_ [ R.text "With a label" ]
4847 , Block.cluster {}
49− [ element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "And text", onChange: handler_ mempty }
50− , element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "", onChange: handler_ mempty }
51− , element Input.component { label: nes (SProxy ∷ _ "This has a label"), placeholder: "A very long placeholder, too..." }
52− , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🐽🤣" }
53− , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), trailing: R.text "🤫" }
54− , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🌭" }
48+ [ element Input.component { label: nes (Proxy ∷ _ "This has a label"), value: "And text", onChange: handler_ mempty }
49+ , element Input.component { label: nes (Proxy ∷ _ "This has a label"), value: "", onChange: handler_ mempty }
50+ , element Input.component { label: nes (Proxy ∷ _ "This has a label"), placeholder: "A very long placeholder, too..." }
51+ , element Input.component { label: nes (Proxy ∷ _ "Pig nose"), leading: R.text "🐽🤣" }
52+ , element Input.component { label: nes (Proxy ∷ _ "Pig nose"), trailing: R.text "🤫" }
53+ , element Input.component { label: nes (Proxy ∷ _ "Pig nose"), leading: R.text "🌭" }
5554 , Block.box
5655 { background: colour.backgroundLayer3
5756 }
5857 [ element Input.component
59− { label: nes (SProxy ∷ _ "Different background")
58+ { label: nes (Proxy ∷ _ "Different background")
6059 , leading: R.text "🌭"
6160 , forceSmallLabel: true
6261 }
@@ -65,36 +64,37 @@ input = do
6564 { background: colour.backgroundLayer1
6665 }
6766 [ element Input.component
68− { label: nes (SProxy ∷ _ "Another background")
67+ { label: nes (Proxy ∷ _ "Another background")
6968 , background: colour.backgroundLayer3
7069 , textColour: "blue"
7170 , placeholderColour: colour.backgroundLayer4
7271 , leading: R.text "🌭"
7372 }
7473 ]
75− , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "⭐", trailing: R.text "🔮" }
74+ , element Input.component { label: nes (Proxy ∷ _ "Pig nose"), leading: R.text "⭐", trailing: R.text "🔮" }
7675 ]
7776 , R.h2_ [ R.text "Generic Input" ]
7877 , Input.component </> { value: "A Generic Input", onChange: handler_ mempty }
7978 , R.h2_ [ R.text "Validation on text Input" ]
80− , element Input.component { type: HTMLInput.Text, label: nes (SProxy ∷ _ "Is undefined a function?"), value: "Yes, why not?", onChange: handler_ mempty, _aria: Object.singleton "invalid" "true" }
81− , element Input.component { type: HTMLInput.Text, label: nes (SProxy ∷ _ "What's the type of null?"), value: "object", onChange: handler_ mempty, _aria: Object.singleton "invalid" "false" }
79+ , element Input.component { type: HTMLInput.Text, label: nes (Proxy ∷ _ "Is undefined a function?"), value: "Yes, why not?", onChange: handler_ mempty, _aria: Object.singleton "invalid" "true" }
80+ , element Input.component { type: HTMLInput.Text, label: nes (Proxy ∷ _ "What's the type of null?"), value: "object", onChange: handler_ mempty, _aria: Object.singleton "invalid" "false" }
8281 , R.h2_ [ R.text "Required fields" ]
8382 , element Input.component
8483 { type: HTMLInput.Text
85− , label: nes (SProxy ∷ _ "I am so important")
84+ , label: nes (Proxy ∷ _ "I am so important")
8685 , _aria: Object.singleton "required" "true"
8786 }
8887 , R.h2_ [ R.text "Overflowing label" ]
8988 , element Input.component
9089 { type: HTMLInput.Text
91− , label: nes (SProxy ∷ _ "Is undefined really a function?")
90+ , label: nes (Proxy ∷ _ "Is undefined really a function?")
9291 }
93− , Input.component </> { type: HTMLInput.Text, label: nes (SProxy ∷ _ "Now this is really just excessively long and you should avoid it.") }
92+ , Input.component </> { type: HTMLInput.Text, label: nes (Proxy ∷ _ "Now this is really just excessively long and you should avoid it.") }
9493 , Input.component
95− </> { css: E.css { width: E.str "500px" }
94+ </>
95+ { css: E.css { width: E.str "500px" }
9696 , type: HTMLInput.Text
97− , label: nes (SProxy ∷ _ "You can avoid this problem by setting a custom width")
97+ , label: nes (Proxy ∷ _ "You can avoid this problem by setting a custom width")
9898 }
9999 , R.h2_ [ R.text "Password" ]
100100 , passComponent </> {}
@@ -126,12 +126,10 @@ input = do
126126 hidePassword /\ modifyHidePassword <- React.useState true
127127 pure
128128 $ Input.component
129− </> { type: if hidePassword then HTMLInput.Password else HTMLInput.Text
130− , trailing:
131− Block.tooltip
132− </> { target: passwordIcon </> { hidePassword, modifyHidePassword }, theTip: R.text if hidePassword then "Show Password" else "Hide Password"
133− }
134− , value: password
135− , onChange: handler targetValue (traverse_ setPassword)
136− , label: nes (Proxy ∷ _ "Password")
137− }
129+ </>
130+ { type: if hidePassword then HTMLInput.Password else HTMLInput.Text
131+ , trailing: passwordIcon </> { hidePassword, modifyHidePassword }
132+ , value: password
133+ , onChange: handler targetValue (traverse_ setPassword)
134+ , label: nes (Proxy ∷ _ "Password")
135+ }
src/Yoga/Block/Atom/Input/Style.purs+3−3
@@ -109,13 +109,13 @@ labelSmallFocusBackground =
109109labelLarge ∷ { left ∷ Number, width ∷ Number } -> Style
110110labelLarge { left, width } =
111111 css
112− { fontSize: str "calc(var(--s0) * 0.85)"
112+ { fontSize: str "var(--s0)"
113113 , padding: _0
114114 , whiteSpace: nowrap -- force on one line
115− , height: str "calc(var(--s0))"
115+ , height: str "var(--s0)"
116116 , maxWidth: str $ i "calc(" width "px - 2ch)"
117117 , textOverflow: str "ellipsis"
118− , marginTop: str "calc(var(--s-1) + var(--s-5))"
118+ , marginTop: str "calc(var(--s0) * 0.5 - var(--s-4))"
119119 , marginLeft: str $ i left "px"
120120 , marginRight: var "--input-side-padding"
121121 , color: str colour.placeholderText
src/Yoga/Block/Atom/Input/View.purs+83−50
@@ -1,8 +1,10 @@
11module Yoga.Block.Atom.Input.View where
22
33import Yoga.Prelude.View
4+
45import Data.String.NonEmpty (NonEmptyString)
56import Effect.Unsafe (unsafePerformEffect)
7+import Foreign.NullOrUndefined (undefined)
68import Foreign.Object (Object)
79import Foreign.Object as Object
810import Framer.Motion as M
@@ -11,6 +13,8 @@ import React.Basic.Hooks (reactComponent)
1113import React.Basic.Hooks as React
1214import Record.Builder as RB
1315import Type.Prelude (Proxy(..))
16+import Unsafe.Coerce (unsafeCoerce)
17+import Untagged.Union (uorToMaybe)
1418import Web.HTML.HTMLInputElement as InputElement
1519import Yoga.Block.Atom.Icon as Icon
1620import Yoga.Block.Atom.Input.Style as Style
@@ -45,18 +49,21 @@ component = rawComponent
4549mkLeftIcon ∷ JSX -> JSX
4650mkLeftIcon icon =
4751 div
48− </* { className: "ry-input-left-icon-container"
52+ </*
53+ { className: "ry-input-left-icon-container"
4954 , css: Style.leftIconContainer
5055 }
51− /> [ Icon.component
52− </> { size: Style.leftIconSize
56+ />
57+ [ Icon.component
58+ </>
59+ { size: Style.leftIconSize
5360 , icon
5461 }
5562 ]
5663
5764rawComponent ∷ ∀ p. ReactComponent (Record p)
5865rawComponent =
59− mkForwardRefComponent "InputContainer" do
66+ mkForwardRefComponent "YogaInput" do
6067 \(props ∷ { | PropsOptional }) propsRef -> React.do
6168 hasFocus /\ setHasFocus <- useState' false
6269 inputBackupRef ∷ NodeRef <- useRef null
@@ -71,19 +78,25 @@ rawComponent =
7178 hasValue = case maybeValue of
7279 Just v -> v /= ""
7380 Nothing -> internalValue /= ""
81+
7482 aria ∷ Object String
7583 aria = props._aria # opToMaybe # fold
84+
7685 labelId ∷ String
7786 labelId = props.id # opToMaybe # fold # (_ <> "-label")
7887 renderSmallLabel = isTruthy props.forceSmallLabel || hasFocus || hasValue
88+
7989 renderLargeLabel ∷ Boolean
8090 renderLargeLabel = not renderSmallLabel
91+
8192 maybeLabelText ∷ Maybe NonEmptyString
8293 maybeLabelText = props.label # opToMaybe
94+
8395 mkLabel ∷ NonEmptyString -> JSX
8496 mkLabel labelText =
8597 Label.component
86− </> { isFocussed: hasFocus
98+ </>
99+ { isFocussed: hasFocus
87100 , isRequired: aria # Object.lookup "required" # (_ == Just "true")
88101 , isInvalid: aria # Object.lookup "invalid" # (_ == Just "true")
89102 , renderLargeLabel
@@ -95,30 +108,33 @@ rawComponent =
95108 , background: props.background ?|| colour.interfaceBackground
96109 , textColour: props.textColour ?|| colour.text
97110 }
111+
98112 leading ∷ Maybe JSX
99113 leading =
100114 opToMaybe props.leading
101− <|> if (props.type <#> (_ == InputTypes.Search)) ?|| false then
115+ <|>
116+ if (props.type <#> (_ == InputTypes.Search)) ?|| false then
102117 Just $ mkLeftIcon SVGIcon.magnifyingGlass
103118 else
104119 Nothing
120+
105121 trailing ∷ Maybe JSX
106122 trailing = opToMaybe props.trailing
123+
107124 maybePlaceholder ∷ Maybe String
108125 maybePlaceholder = do
109126 given <- props.placeholder # opToMaybe
110127 if isJust maybeLabelText && hasFocus then Just given else Nothing
111− onBlur =
112− handler preventDefault
113− ( const do
114− when hasFocus $ setHasFocus false
115− el <- getHTMLElementFromRef ref
116− let inputEl = InputElement.fromHTMLElement =<< el
117− for_ inputEl \ie -> do
118− v <- InputElement.value ie
119− setValue v
120− )
121− onFocus = handler preventDefault (const $ unless hasFocus $ setHasFocus true)
128+
129+ onBlur = handler_ do
130+ when hasFocus $ setHasFocus false
131+ el <- getHTMLElementFromRef ref
132+ let inputEl = InputElement.fromHTMLElement =<< el
133+ for_ inputEl \ie -> do
134+ v <- InputElement.value ie
135+ setValue v
136+
137+ onFocus = handler_ (unless hasFocus $ setHasFocus true)
122138 onChange = handler targetValue (setValue <<< fromMaybe "")
123139 let
124140 inputProps ∷ { | PropsOptional }
@@ -129,28 +145,33 @@ rawComponent =
129145 , onChange = cast (composeHandler onChange props.onChange)
130146 , placeholder = maybePlaceholder # maybeToOp
131147 , _aria =
132− if props.label # opToMaybe # isJust then
133− cast (aria # Object.insert "labelledby" labelId)
134− else
135− cast (aria)
148+ if props.label # opToMaybe # isJust then
149+ cast (aria # Object.insert "labelledby" labelId)
150+ else
151+ cast (aria)
136152 }
153+
137154 theInput =
138155 HTMLInput.componentOptional
139− </> ( (cast ∷ _ -> { | HTMLInput.PropsF OptionalProp (InputWritablePropsF OptionalProp ()) })
140− ( inputProps
141− # RB.build
142− ( RB.delete (Proxy ∷ _ "leading")
143− >>> RB.delete (Proxy ∷ _ "label")
144− >>> RB.delete (Proxy ∷ _ "trailing")
145− >>> RB.delete (Proxy ∷ _ "inputRef")
146− >>> RB.delete (Proxy ∷ _ "forceSmallLabel")
147− >>> RB.insert (Proxy ∷ _ "ref") inputRef
148− )
149− )
156+ </>
157+ ( ( (cast ∷ _ -> { | HTMLInput.PropsF OptionalProp (InputWritablePropsF OptionalProp ()) })
158+ ( ( inputProps
159+ # RB.build
160+ ( RB.delete (Proxy ∷ _ "leading")
161+ >>> RB.delete (Proxy ∷ _ "label")
162+ >>> RB.delete (Proxy ∷ _ "trailing")
163+ >>> RB.delete (Proxy ∷ _ "inputRef")
164+ >>> RB.delete (Proxy ∷ _ "forceSmallLabel")
165+ >>> RB.insert (Proxy ∷ _ "ref") inputRef
166+ )
167+ )
168+ )
169+ ) # deleteUndefineds
150170 )
151171 inputContainer =
152172 rawContainer
153− </ { hasFocus: hasFocus
173+ </
174+ { hasFocus: hasFocus
154175 , isInvalid: aria # Object.lookup "invalid" <#> (_ == "true") # maybeToOp
155176 , css: props.css
156177 , background: props.background
@@ -158,7 +179,8 @@ rawComponent =
158179 , textColor: props.textColour
159180 , ref
160181 }
161− /> [ leading # foldMap \l -> div </ {} /> [ l ]
182+ />
183+ [ leading # foldMap \l -> div </ {} /> [ l ]
162184 , theInput
163185 , trailing # foldMap \t -> div </ {} /> [ t ]
164186 ]
@@ -167,50 +189,61 @@ rawComponent =
167189 Nothing -> inputContainer
168190 Just labelText ->
169191 div
170− </* { className: "ry-label-and-input-wrapper"
192+ </*
193+ { className: "ry-label-and-input-wrapper"
171194 , css: Style.labelAndInputWrapper <>? props.css
172195 }
173196 /> [ inputContainer, mkLabel labelText ]
174197
175−passwordIcon ∷
176− ReactComponent
177− { hidePassword ∷ Boolean
178− , modifyHidePassword ∷ (Boolean -> Boolean) -> Effect Unit
179− }
198+passwordIcon
199+ ∷ ReactComponent
200+ { hidePassword ∷ Boolean
201+ , modifyHidePassword ∷ (Boolean -> Boolean) -> Effect Unit
202+ }
180203passwordIcon =
181204 unsafePerformEffect
182205 $ reactComponent "Password Icon" \props -> React.do
183206 pure $ div
184− </* { onClick: handler preventDefault \_ -> props.modifyHidePassword not
207+ </*
208+ { onClick: handler preventDefault \_ -> props.modifyHidePassword not
185209 , className: "ry-input-right-icon-container"
186210 , css: Style.rightIconContainer
187211 }
188− /> [ M.animatePresence
189− </ { exitBeforeEnter: true
212+ />
213+ [ M.animatePresence
214+ </
215+ { exitBeforeEnter: true
190216 }
191− /> [ if props.hidePassword then
217+ />
218+ [ if props.hidePassword then
192219 M.div
193− </ { key: "eyeOpen"
220+ </
221+ { key: "eyeOpen"
194222 , initial: M.initial $ css { scaleY: 0.2 }
195223 , animate: M.animate $ css { scaleY: 1.0 }
196224 , exit: M.exit $ css {}
197225 , transition: M.transition { scaleY: { type: "spring", duration: 0.12, bounce: 0.00 } }
198226 }
199− /> [ Icon.component
200− </> { size: Style.rightIconSize
227+ />
228+ [ Icon.component
229+ </>
230+ { size: Style.rightIconSize
201231 , icon: SVGIcon.eyeOpen
202232 }
203233 ]
204234 else
205235 M.div
206− </ { key: "eyeClosed"
236+ </
237+ { key: "eyeClosed"
207238 , initial: M.initial $ css { scaleY: 1.0 }
208239 , animate: M.animate $ css { scaleY: 0.4 }
209240 , exit: M.exit $ css { scaleY: 0.2 }
210241 , transition: M.transition { scaleY: { type: "spring", duration: 0.12, bounce: 0.00 } }
211242 }
212− /> [ Icon.component
213− </> { size: Style.rightIconSize
243+ />
244+ [ Icon.component
245+ </>
246+ { size: Style.rightIconSize
214247 , icon: SVGIcon.eyeClosed
215248 }
216249 ]
src/Yoga/Block/Atom/Input/View/Container.purs+43−40
@@ -1,14 +1,16 @@
11module Yoga.Block.Atom.Input.View.Container where
22
33import Yoga.Prelude.View
4+
45import Data.Array as Array
56import Data.Interpolate (i)
6−import Foreign.Object as Object
7+import Foreign.NullOrUndefined (undefined)
78import Framer.Motion as M
89import Partial.Unsafe (unsafeCrashWith)
910import React.Basic.DOM (CSS, css)
1011import React.Basic.Emotion (Style)
1112import React.Basic.Hooks as React
13+import Unsafe.Coerce (unsafeCoerce)
1214import Yoga.Block.Atom.Input.Style as Style
1315import Yoga.Block.Hook.UseResize (useResize)
1416
@@ -48,25 +50,26 @@ rawContainer =
4850 containerVariantLabels = mkContainerVariantLabels containerVariants
4951 result =
5052 M.div
51− </* { variants: M.variants containerVariants
52− , initial: M.initial false
53− , animate:
54− M.animate
55− if props.hasFocus then
56− containerVariantLabels.focussed
57− else
58− containerVariantLabels.blurred
59− , className: "ry-input-container"
60− , key: show sizes.innerWidth -- redraw
61− , css: Style.inputContainer props
62− , _data:
63− props.isInvalid
64− # foldMap \isInvalid ->
65− Object.fromHomogeneous
66− { "invalid": show isInvalid
67− }
68− , ref
69− }
53+ </*
54+ ( { variants: M.variants containerVariants
55+ , initial: M.initial false
56+ , animate:
57+ M.animate
58+ if props.hasFocus then
59+ containerVariantLabels.focussed
60+ else
61+ containerVariantLabels.blurred
62+ , className: "ry-input-container"
63+ , key: show sizes.innerWidth -- redraw
64+ , css: Style.inputContainer props
65+ , ref
66+ } `unsafeAddProps`
67+ { "data-invalid":
68+ props.isInvalid
69+ # opToMaybe
70+ # maybe (unsafeCoerce undefined) show
71+ }
72+ )
7073 /> props.children
7174 pure result
7275
@@ -133,31 +136,31 @@ mkPath { width, height } = do
133136 p ∷ Number -> Number -> Point
134137 p x y = { x, y }
135138
136−mkContainerVariantLabels ∷
137− { blurred ∷ CSS
138− , focussed ∷ CSS
139− } ->
140− { blurred ∷ M.VariantLabel
141− , focussed ∷ M.VariantLabel
142− }
139+mkContainerVariantLabels
140+ ∷ { blurred ∷ CSS
141+ , focussed ∷ CSS
142+ }
143+ -> { blurred ∷ M.VariantLabel
144+ , focussed ∷ M.VariantLabel
145+ }
143146mkContainerVariantLabels = M.makeVariantLabels
144147
145−mkContainerVariants ∷
146− { width ∷ Number, height ∷ Number } ->
147− { blurred ∷ CSS
148− , focussed ∷ CSS
149− }
148+mkContainerVariants
149+ ∷ { width ∷ Number, height ∷ Number }
150+ -> { blurred ∷ CSS
151+ , focussed ∷ CSS
152+ }
150153mkContainerVariants dimensions =
151154 { focussed:
152− css
153− { clipPath: clipPathFocussed
154− , transition: { duration: 0.6 }
155− }
155+ css
156+ { clipPath: clipPathFocussed
157+ , transition: { duration: 0.6 }
158+ }
156159 , blurred:
157− css
158− { clipPath:
159− drawPathUntil (Array.length path + 1) path
160− }
160+ css
161+ { clipPath:
162+ drawPathUntil (Array.length path + 1) path
163+ }
161164 }
162165 where
163166 path = mkPath dimensions
src/Yoga/Block/Atom/Input/View/Label.purs+37−36
@@ -31,7 +31,7 @@ type Props =
3131component ∷ ReactComponent Props
3232component =
3333 unsafePerformEffect
34− $ reactComponent "Input Label" \props@{ inputRef, parentRef } -> React.do
34+ $ reactComponent "InputLabel" \props@{ inputRef, parentRef } -> React.do
3535 maybeOffsets /\ setOffsets <- useState' Nothing
3636 -- this is so complicated because we need to take scale into account
3737 useLayoutEffectAlways do
@@ -78,48 +78,49 @@ component =
7878 # foldMap case _ of
7979 Nothing ->
8080 M.div
81− </* { className: "ry-input-label-small"
82− , layout: M.layout true
83− , layoutId: M.layoutId "ry-input-label"
84− , css: Style.labelSmall props.background props.textColour
85− , transition: M.transition { duration: 0.18, ease: "easeOut" }
86− , _data:
87− Object.fromHomogeneous
88− { "has-focus": show props.isFocussed
89− , "invalid": show props.isInvalid
90− , "required": show props.isRequired
81+ </*
82+ ( { className: "ry-input-label-small"
83+ , layout: M.layout true
84+ , layoutId: M.layoutId ("ry-input-label-" <> props.labelId)
85+ , css: Style.labelSmall props.background props.textColour
86+ , transition: M.transition { duration: 0.18, ease: "easeOut" }
87+ , initial: M.initial false
88+ } `unsafeAddProps`
89+ { "data-has-focus": props.isFocussed
90+ , "data-invalid": show props.isInvalid
91+ , "data-required": show props.isRequired
9192 }
92− , initial: M.initial false
93− }
93+ )
9494 Just { largeLeft, largeWidth } ->
9595 M.div
96− </* { className:
97− if props.renderLargeLabel then
98− "ry-input-label-large"
99− else
100− "ry-input-label-small"
101− , layout: M.layout true
102− , layoutId: M.layoutId "ry-input-label"
103− , css:
104− if props.renderLargeLabel then
105− Style.labelLarge { left: largeLeft, width: largeWidth }
106− else
107− Style.labelSmall props.background props.textColour
108− , transition: M.transition { duration: 0.18, ease: "easeOut" }
109− , _data:
110− Object.fromHomogeneous
111− { "has-focus": show props.isFocussed
112− , "invalid": show props.isInvalid
113− , "required": show props.isRequired
96+ </*
97+ ( { className:
98+ if props.renderLargeLabel then
99+ "ry-input-label-large"
100+ else
101+ "ry-input-label-small"
102+ , layout: M.layout true
103+ , layoutId: M.layoutId ("ry-input-label-" <> props.labelId)
104+ , css:
105+ if props.renderLargeLabel then
106+ Style.labelLarge { left: largeLeft, width: largeWidth }
107+ else
108+ Style.labelSmall props.background props.textColour
109+ , transition: M.transition { duration: 0.18, ease: "easeOut" }
110+ , initial: M.initial false
111+ } `unsafeAddProps`
112+ { "data-has-focus": props.isFocussed
113+ , "data-invalid": show props.isInvalid
114+ , "data-required": show props.isRequired
114115 }
115− , initial: M.initial false
116− }
116+ )
117117 labelSpan =
118118 M.span
119− </ { layout: M.layout true
120− , layoutId: M.layoutId "ry-input-label-text"
119+ </
120+ { layout: M.layout true
121+ , layoutId: M.layoutId ("ry-input-label-text-" <> props.labelId)
121122 , htmlFor: props.inputId
122123 , style: css { pointerEvents: "none" }
123124 , id: props.labelId
124125 }
125− pure result
126+ pure result
src/Yoga/Block/Atom/Popover.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Yoga.Block.Atom.Popover
2− ( module Yoga.Block.Atom.Popover.View
3− ) where
4−
5−import Yoga.Block.Atom.Popover.View (component, Props, MandatoryProps)
src/Yoga/Block/Atom/Popover/Story.pursdeleted−57
@@ -1,57 +0,0 @@
1−module Yoga.Block.Atom.Popover.Story (default, popover) where
2−
3−import Yoga.Prelude.View
4−import Effect.Uncurried (mkEffectFn1)
5−import Effect.Unsafe (unsafePerformEffect)
6−import React.Basic.DOM (h2_, text)
7−import React.Basic.DOM as R
8−import React.Basic.Emotion as E
9−import React.Basic.Hooks as React
10−import Unsafe.Coerce (unsafeCoerce)
11−import Yoga.Block as Block
12−import Yoga.Block.Container.Style as Styles
13−
14−default ∷
15− { decorators ∷ Array (Effect JSX -> JSX)
16− , title ∷ String
17− }
18−default =
19− { title: "Atom/Popover"
20− , decorators:
21− [ \storyFn ->
22− div
23− </ {}
24− /> [ element E.global { styles: Styles.global }
25− , unsafePerformEffect storyFn
26− ]
27− ]
28− }
29−
30−popover ∷ Effect JSX
31−popover = do
32− example <- mkBasicExample
33− pure
34− $ fragment
35− [ div </ {}
36− /> [ h2_ [ text "A popover" ]
37− , element example {}
38− ]
39− ]
40− where
41− nullRef ∷ NodeRef
42− nullRef = unsafeCoerce null
43−
44− mkBasicExample =
45− React.reactComponent "Popper example" \_p -> React.do
46− referenceElement /\ setReferenceElement <- React.useState' nullRef
47− let
48− popover' =
49− Block.popover
50− </ { referenceElement }
51− /> [ R.div_ [ R.text "Inside the Popover" ] ]
52− pure
53− $ fragment
54− [ R.span' </ { ref: unsafeCoerce (mkEffectFn1 setReferenceElement) }
55− /> [ R.text "Hi!" ]
56− , popover'
57− ]
src/Yoga/Block/Atom/Popover/Style.pursdeleted−129
@@ -1,129 +0,0 @@
1−module Yoga.Block.Atom.Popover.Style where
2−
3−import Yoga.Prelude.Style
4−import Data.Interpolate (i)
5−import Yoga.Block.Container.Style (colour, size)
6−
7−type Props :: forall k. (Type -> k) -> Row k -> Row k
8−type Props f r =
9− ( css ∷ f Style
10− | r
11− )
12−
13−content ∷ Style
14−content =
15− css
16− { zIndex: str "-1"
17− }
18−
19−popper ∷ OptionalProp String -> Style
20−popper _ =
21− css
22− { "&[data-popper-placement^='top'] > #arrow":
23− nest
24− { bottom: px (arrowSize / -2)
25− , "&::before, &::after":
26− nest
27− { borderTopColor: str "transparent"
28− , borderLeftColor: str "transparent"
29− , clipPath: str $ i "polygon( " arrowSize "px " arrowSize "px, 0px " arrowSize "px, " arrowSize "px 0px)"
30− }
31− , "&::after": nest { bottom: px zero }
32− , "&::before": nest { bottom: px (1) }
33− }
34− , "&[data-popper-placement^='bottom'] > #arrow":
35− nest
36− { top: px (arrowSize / -2)
37− , "&::before, &::after":
38− nest
39− { borderBottomColor: str "transparent"
40− , borderRightColor: str "transparent"
41− , clipPath: str $ i "polygon(0px 0px, " arrowSize "px 0px, 0px " arrowSize "px)"
42− }
43− , "&::after": nest { top: px zero }
44− , "&::before": nest { top: px (1) }
45− }
46− , "&[data-popper-placement^='left'] > #arrow":
47− nest
48− { right: px (arrowSize / -2)
49− , "&::before, &::after":
50− nest
51− { borderBottomColor: str "transparent"
52− , borderLeftColor: str "transparent"
53− , clipPath: str $ i "polygon(0px 0px, " arrowSize "px 0px, " arrowSize "px " arrowSize "px)"
54− }
55− , "&::after": nest { right: px zero }
56− , "&::before": nest { right: px (1) }
57− }
58− , "&[data-popper-placement^='right'] > #arrow":
59− nest
60− { left: px (arrowSize / -2)
61− , "&::before, &::after":
62− nest
63− { borderTopColor: str "transparent"
64− , borderRightColor: str "transparent"
65− , clipPath: str $ i "polygon(" arrowSize "px " arrowSize "px, 0px " arrowSize "px, 0px 0px)"
66− }
67− , "&::after": nest { left: px zero }
68− , "&::before": nest { left: px (1) }
69− }
70− , zIndex: str "6"
71− , border: str $ "1px solid " <> colour.popperOuterBorder
72− , boxSizing: contentBox
73− , borderRadius: str size.s
74− , position: relative
75− , "&:before":
76− nest
77− { content: str "''"
78− , position: absolute
79− , border: str $ "1px solid " <> colour.popperInnerBorder
80− , borderRadius: str $ "calc(" <> size.s <> " - 1px" <> ")"
81− , boxShadow: str $ "var(--s-5) 0 var(--s-2) rgba(0,0,0,0.1)"
82− , background: str colour.popperBackground
83− , backdropFilter: str "blur(10px)"
84− , zIndex: str "-1"
85− , top: px 0
86− , boxSizing: contentBox
87− , left: px 0
88− , right: px 0
89− , bottom: px 0
90− }
91− }
92−
93−arrow ∷ Style
94−arrow =
95− common
96− <> css
97− { visibility: hidden
98− , "&::before":
99− nested
100− $ common
101− <> css
102− { visibility: visible
103− , content: str "''"
104− , transform: str "rotate(45deg)"
105− , border: str $ "1px solid " <> colour.popperInnerBorder
106− , background: str colour.popperBackgroundNoAlpha
107− }
108− , "&::after":
109− nested
110− $ common
111− <> css
112− { visibility: visible
113− , content: str "''"
114− , transform: str "rotate(45deg)"
115− , border: str $ "1px solid " <> colour.popperOuterBorder
116− , zIndex: str "-1"
117− }
118− }
119− where
120− common =
121− css
122− { position: absolute
123− , width: px arrowSize
124− , height: px arrowSize
125− , boxSizing: borderBox
126− }
127−
128−arrowSize :: Int
129−arrowSize = 14
src/Yoga/Block/Atom/Popover/View.pursdeleted−114
@@ -1,114 +0,0 @@
1−module Yoga.Block.Atom.Popover.View (component, MandatoryProps, Props, PropsF) where
2−
3−import Yoga.Prelude.View
4−import Effect.Uncurried (mkEffectFn1)
5−import React.Basic.DOM (createPortal)
6−import React.Basic.Hooks as React
7−import React.Basic.Popper (modifierArrow, modifierMatchReferenceSize, modifierOffset, nullRef)
8−import React.Basic.Popper.Hook (usePopper)
9−import React.Basic.Popper.Placement.Types (Placement(..))
10−import React.Basic.Popper.Placement.Types as Placement
11−import Unsafe.Coerce (unsafeCoerce)
12−import Web.DOM.Element (Element)
13−import Yoga.Block.Atom.Popover.Style as Style
14−import Yoga.Block.Container.View as Container
15−import Yoga.Block.Internal (findElementByIdInDocument)
16−
17−type PropsF f =
18− ( className ∷ f String
19− , placement ∷ f Placement
20− , renderArrow ∷ f Boolean
21− , background ∷ f String
22− , borderRadius ∷ f String
23− , offsets ∷ f { xOffset ∷ Number, yOffset ∷ Number }
24− , targetElement ∷ f Element
25− | Style.Props f (MandatoryProps DivProps)
26− )
27−
28−type MandatoryProps r =
29− ( children ∷ Array JSX
30− , referenceElement ∷ NodeRef
31− | r
32− )
33−
34−type Props =
35− PropsF Id
36−
37−type PropsOptional =
38− PropsF OptionalProp
39−
40−component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | MandatoryProps p }
41−component = rawComponent
42−
43−rawComponent ∷ ∀ p. ReactComponent { | p }
44−rawComponent =
45− mkForwardRefComponent "Popover" do
46− \(props ∷ { | PropsOptional }) ref -> React.do
47− -- Hooks
48− arrowElement /\ setArrowElement <- React.useState' nullRef
49− popperElement /\ setPopperElement <- React.useState' nullRef
50− popoverContainer /\ setPopoverContainer <- React.useState' Nothing
51− useEffectOnce do
52− maybeElem <- findElementByIdInDocument Container.tooltipContainerId
53− setPopoverContainer maybeElem
54− mempty
55− let renderArrow = props.renderArrow # isTruthy
56− let placement = props.placement ?|| Placement Placement.Auto Nothing
57− let
58− { xOffset, yOffset } =
59− props.offsets
60− ?|| if not renderArrow then
61− zero
62− else case placement of
63− Placement Placement.Bottom _ -> { xOffset: 0.0, yOffset: 8.0 }
64− Placement Placement.Top _ -> { xOffset: 0.0, yOffset: 8.0 }
65− Placement Placement.Left _ -> { xOffset: 8.0, yOffset: 0.0 }
66− Placement Placement.Right _ -> { xOffset: 8.0, yOffset: 0.0 }
67− Placement Placement.Auto _ -> { xOffset: 0.0, yOffset: 0.0 }
68− { styles, attributes } <-
69− usePopper props.referenceElement popperElement
70− { modifiers:
71− [ modifierOffset { x: xOffset, y: yOffset }
72− , modifierMatchReferenceSize
73− ]
74− <> guard renderArrow [ modifierArrow { element: arrowElement, padding: 8 } ]
75− , placement: props.placement <#> Placement.render # unsafeUnOptional
76− }
77− -- Handlers
78− -- Elements
79− let
80− result =
81− popper
82− [ content
83− , guard renderArrow arrow
84− ]
85− content =
86− emotionDiv
87− ref
88− props
89− { className: "ry-popover-popper-element-content"
90− , css: Style.content
91− , children: props.children
92− }
93− popper =
94− div
95− </* { className: "ry-popover-popper-element"
96− , css: Style.popper props.background
97− , ref: unsafeCoerce (mkEffectFn1 setPopperElement)
98− , style: styles.popper
99− , _data: attributes.popper
100− }
101− arrow =
102− div
103− </*> { className: "ry-popover-arrow-element"
104− , css: Style.arrow
105− , ref: unsafeCoerce (mkEffectFn1 setArrowElement)
106− , style: styles.arrow
107− , _data: attributes.arrow
108− , id: "arrow"
109− }
110− pure case opToMaybe props.targetElement of
111− Just target -> createPortal result target
112− Nothing -> case popoverContainer of
113− Just pc -> createPortal result pc
114− Nothing -> result
src/Yoga/Block/Atom/Segmented/View.purs+39−32
@@ -4,6 +4,7 @@ import Yoga.Prelude.View
44
55import Data.Array as A
66import Data.Newtype (wrap)
7+import Data.Ord (abs)
78import Data.Time.Duration (Milliseconds(..))
89import Data.Traversable (traverse)
910import Data.TwoOrMore (TwoOrMore)
@@ -11,7 +12,6 @@ import Data.TwoOrMore as TwoOrMore
1112import Effect.Aff (delay)
1213import Effect.Unsafe (unsafePerformEffect)
1314import Foreign.Object as Object
14−import Math as Math
1515import React.Basic.DOM (css)
1616import React.Basic.DOM as R
1717import React.Basic.Emotion as E
@@ -49,12 +49,12 @@ component =
4949 let
5050 maxIndex = TwoOrMore.length buttonContents - 1
5151 updateIndex idx = do
52− let
52+ let
5353 newItem = fromMaybe'
54− (\_ -> TwoOrMore.head buttonContents)
55− (buttonContents TwoOrMore.!! idx)
54+ (\_ -> TwoOrMore.head buttonContents)
55+ (buttonContents TwoOrMore.!! idx)
5656 updateActiveItem newItem idx
57−
57+
5858 updateTo toIndex = do
5959 for_ itemRefs do blurAtIndex activeIndex
6060 updateIndex toIndex
@@ -73,8 +73,8 @@ component =
7373 -- Ensure redraw on window resize
7474 newWindowSize <- useResize
7575 useAff newWindowSize do
76− let δw = Math.abs (newWindowSize.innerWidth - windowSize.innerWidth)
77− let δh = Math.abs (newWindowSize.innerHeight - windowSize.innerHeight)
76+ let δw = abs (newWindowSize.innerWidth - windowSize.innerWidth)
77+ let δh = abs (newWindowSize.innerHeight - windowSize.innerHeight)
7878 delay
7979 if δw < 10.0 || δh < 10.0 then
8080 100.0 # Milliseconds
@@ -87,14 +87,17 @@ component =
8787 let
8888 children ∷ Array JSX
8989 children = refsAndContents <#> mapWithIndex contentToChild # maybe mempty TwoOrMore.toArray
90+
9091 refsAndContents ∷ Maybe (TwoOrMore (Item /\ Ref (Nullable Node)))
9192 refsAndContents = TwoOrMore.zip buttonContents <$> itemRefs
93+
9294 contentToChild ∷ Int -> (Item /\ Ref (Nullable Node)) -> JSX
9395 contentToChild idx ({ id, value } /\ ref) = do
9496 let isLast = idx + 1 == TwoOrMore.length buttonContents
9597 let isFirst = idx == 0
9698 button
97− </* { key: show idx
99+ </*
100+ { key: show idx
98101 , ref
99102 , css: Style.button { isFirst, isLast }
100103 , className: "ry-segmented-button"
@@ -104,40 +107,44 @@ component =
104107 , tabIndex: if idx == activeIndex then 0 else -1
105108 , id
106109 , _aria:
107− Object.fromHomogeneous
108− { selected: show (idx == activeIndex)
109− }
110+ Object.fromHomogeneous
111+ { selected: show (idx == activeIndex)
112+ }
110113 }
111− /> [ span
112− </* { className: "ry-segmented-button__content"
114+ />
115+ [ span
116+ </*
117+ { className: "ry-segmented-button__content"
113118 , css: Style.buttonContent { isFirst, isLast }
114119 , tabIndex: if idx == activeIndex then 0 else -1
115120 }
116− /> [ R.text value
121+ />
122+ [ R.text value
117123 ]
118124 ]
119125 pure
120126 $ E.element R.div'
121− $ { css: Style.cluster
127+ $
128+ { css: Style.cluster
122129 , className: "ry-segmented-container"
123130 , children:
124− [ E.element R.div'
125− { className: "ry-segmented"
126− , css: Style.segmented
127− , role: "tablist"
128− , children:
129− itemRefs
130− # foldMap \activeItemRefs ->
131− React.element ActiveIndicator.component
132− { activeItemRefs
133− , activeItemIndex: activeIndex
134− , buttonContents
135− , updateActiveItem
136− , windowSize
137− }
138− A.: children
139− }
140− ]
131+ [ E.element R.div'
132+ { className: "ry-segmented"
133+ , css: Style.segmented
134+ , role: "tablist"
135+ , children:
136+ itemRefs
137+ # foldMap \activeItemRefs ->
138+ React.element ActiveIndicator.component
139+ { activeItemRefs
140+ , activeItemIndex: activeIndex
141+ , buttonContents
142+ , updateActiveItem
143+ , windowSize
144+ }
145+ A.: children
146+ }
147+ ]
141148 }
142149
143150getHTMLElementAtIndex ∷ Int -> TwoOrMore (NodeRef) -> Effect (Maybe HTMLElement)
src/Yoga/Block/Atom/Segmented/View/ActiveIndicator.purs+3−5
@@ -2,11 +2,10 @@ module Yoga.Block.Atom.Segmented.View.ActiveIndicator (Props, component) where
22
33import Yoga.Prelude.View
44
5−import Control.MonadZero as MZ
5+import Control.Alternative as Alternative
66import Data.Traversable (traverse)
77import Data.TwoOrMore (TwoOrMore)
88import Data.TwoOrMore as TwoOrMore
9−import Effect.Class.Console as Console
109import Effect.Unsafe (unsafePerformEffect)
1110import Foreign.Object as Object
1211import Framer.Motion (VariantLabel)
@@ -110,7 +109,6 @@ component =
110109 setDragXRef (Just (pi.point.x - bbox.left))
111110 , onDrag:
112111 Motion.onDrag \_ pi -> do
113− Console.log "Marlene on the wall"
114112 maybeDragX <- readRef maybeDragXRef
115113 when (isJust maybeDragX) do
116114 maybeBbox <- getBoundingBoxFromRef (TwoOrMore.head props.activeItemRefs)
@@ -179,8 +177,8 @@ findOverlapping activeIndex styles x =
179177 let fst = TwoOrMore.head styles
180178 let lst = TwoOrMore.last styles
181179 let inside e = (e.left < x) && (e.left + e.width) >= x
182− let tooFarLeft = MZ.guard (x <= fst.left + fst.width) $> 0
183− let tooFarRight = MZ.guard (x >= lst.left) $> TwoOrMore.length styles - 1
180+ let tooFarLeft = Alternative.guard (x <= fst.left + fst.width) $> 0
181+ let tooFarRight = Alternative.guard (x >= lst.left) $> TwoOrMore.length styles - 1
184182 TwoOrMore.findIndex inside styles <|> tooFarLeft <|> tooFarRight
185183
186184handleDrag
src/Yoga/Block/Atom/Tooltip.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Yoga.Block.Atom.Tooltip
2− ( module Yoga.Block.Atom.Tooltip.View
3− ) where
4−
5−import Yoga.Block.Atom.Tooltip.View (Props, MandatoryProps, component)
src/Yoga/Block/Atom/Tooltip/Spec.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Yoga.Block.Atom.Tooltip.Spec where
2−
3−import Yoga.Prelude.Spec
4−import React.Basic.DOM as R
5−import Yoga.Block.Atom.Tooltip as Tooltip
6−
7−spec ∷ Spec Unit
8−spec =
9− after_ cleanup do
10− describe "The tooltip" do
11− it "renders without errors" do
12− void
13− $ renderComponent Tooltip.component
14− { theTip: R.text "Tip"
15− , target: R.text "Target"
16− }
src/Yoga/Block/Atom/Tooltip/Story.pursdeleted−39
@@ -1,39 +0,0 @@
1−module Yoga.Block.Atom.Tooltip.Story where
2−
3−import Prelude
4−import Effect (Effect)
5−import Effect.Unsafe (unsafePerformEffect)
6−import React.Basic (JSX, element, fragment)
7−import React.Basic.DOM as R
8−import React.Basic.Emotion as E
9−import Yoga (el)
10−import Yoga.Block.Atom.Tooltip as Tooltip
11−import Yoga.Block.Container.Style as Styles
12−
13−default ∷
14− { decorators ∷ Array (Effect JSX -> JSX)
15− , title ∷ String
16− }
17−default =
18− { title: "Atom/Tooltip"
19− , decorators:
20− [ \storyFn ->
21− R.div_
22− [ element E.global { styles: Styles.global }
23− , unsafePerformEffect storyFn
24− ]
25− ]
26− }
27−
28−tooltip ∷ Effect JSX
29−tooltip = do
30− pure
31− $ fragment
32− [ R.div_
33− [ R.h2_ [ R.text "Basics" ]
34− , element Tooltip.component
35− { theTip: R.text "Hi"
36− , target: el R.button' {} [ R.text "Holzkop" ]
37− }
38− ]
39− ]
src/Yoga/Block/Atom/Tooltip/Style.pursdeleted−58
@@ -1,58 +0,0 @@
1−module Yoga.Block.Atom.Tooltip.Style where
2−
3−import Yoga.Prelude.Style
4−import Yoga.Block.Container.Style (colour)
5−
6−type Props :: forall k. (Type -> k) -> Row k -> Row k
7−type Props f r =
8− ( css ∷ f Style
9− , backgroundColour ∷ f Color
10− | r
11− )
12−
13−backgroundColour ∷ String
14−backgroundColour = colour.text
15−
16−arrow ∷ ∀ r. { | Props OptionalProp r } -> Style
17−arrow props =
18− css
19− { position: str "absolute"
20− , width: str "12px"
21− , height: str "12px"
22− , zIndex: str "0"
23− , "&::before":
24− nest
25− { position: str "absolute"
26− , width: str "12px"
27− , height: str "12px"
28− , borderRadius: str "2px"
29− , content: str "''"
30− , transform: str "rotate(45deg)"
31− , background: str $ (cssStringRGBA <$> props.backgroundColour) ?|| backgroundColour
32− }
33− }
34−
35−content ∷ ∀ r. { | Props OptionalProp r } -> Style
36−content props =
37− css
38− { background: str $ (cssStringRGBA <$> props.backgroundColour) ?|| backgroundColour
39− , minWidth: str "50px"
40− , padding: str "6px"
41− , zIndex: str "-1"
42− , color: str colour.background
43− , boxShadow: str "0 1px 8px rgba(0,0,0,0.33)"
44− , borderRadius: var "--s-2"
45− }
46−
47−popper ∷ Style
48−popper =
49− css
50− { "&[data-popper-placement^='top'] > * > .popper-arrow":
51− nest { bottom: str "-4px" }
52− , "&[data-popper-placement^='bottom'] > * > .popper-arrow":
53− nest { top: str "-4px" }
54− , "&[data-popper-placement^='left'] > * > .popper-arrow":
55− nest { right: str "-4px" }
56− , "&[data-popper-placement^='right'] > * > .popper-arrow":
57− nest { left: str "-4px" }
58− }
src/Yoga/Block/Atom/Tooltip/View.pursdeleted−126
@@ -1,126 +0,0 @@
1−module Yoga.Block.Atom.Tooltip.View (component, MandatoryProps, Props, PropsF) where
2−
3−import Yoga.Prelude.View
4−import Effect.Aff (Milliseconds(..), delay)
5−import Effect.Uncurried (mkEffectFn1)
6−import Framer.Motion as Motion
7−import React.Basic.DOM (css)
8−import React.Basic.DOM as R
9−import React.Basic.Hooks as React
10−import React.Basic.Hooks.Aff (useAff)
11−import React.Basic.Popper (modifierArrow, modifierOffset, nullRef)
12−import React.Basic.Popper.Hook (usePopper)
13−import Unsafe.Coerce (unsafeCoerce)
14−import Yoga.Block.Atom.Tooltip.Style as Style
15−
16−type PropsF f =
17− ( className ∷ f String
18− , hideDelay ∷ f Milliseconds
19− | Style.Props f (MandatoryProps ())
20− )
21−
22−type MandatoryProps r =
23− ( theTip ∷ JSX
24− , target ∷ JSX
25− | r
26− )
27−
28−type Props =
29− PropsF Id
30−
31−type PropsOptional =
32− PropsF OptionalProp
33−
34−component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | MandatoryProps p }
35−component = rawComponent
36−
37−rawComponent ∷ ∀ p. ReactComponent (Record p)
38−rawComponent =
39− mkForwardRefComponent "Tooltip" do
40− \(props ∷ { | PropsOptional }) _ref -> React.do
41− -- Hooks
42− referenceElement /\ setReferenceElement <- React.useState' nullRef
43− popperElement /\ setPopperElement <- React.useState' nullRef
44− arrowElement /\ setArrowElement <- React.useState' nullRef
45− { styles, attributes } <-
46− usePopper referenceElement popperElement
47− { modifiers:
48− [ modifierArrow { element: arrowElement, padding: 8 }
49− , modifierOffset { x: 0.0, y: 12.0 }
50− ]
51− }
52− visible /\ setVisible <- React.useState' false
53− touching /\ setTouching <- React.useState' false
54− hovering /\ setHovering <- React.useState' false
55− useAff hovering do
56− if hovering then
57− setVisible true # liftEffect
58− else do
59− delay (props.hideDelay ?|| (0.0 # Milliseconds))
60− setVisible false # liftEffect
61− useAff touching do
62− if touching then do
63− delay (1000.0 # Milliseconds)
64− setVisible true # liftEffect
65− else do
66− delay (props.hideDelay ?|| (450.0 # Milliseconds))
67− setVisible false # liftEffect
68− -- Handlers
69− let
70− hoveredIn = setHovering true
71− hoveredOut = setHovering false
72− touchStarted = setTouching true
73− touchEnded = setTouching false
74− -- Elements
75− let
76− result =
77− fragment
78− $ [ refElem [ props.target ]
79− , popperEl
80− [ animatePresence
81− $ guard visible
82− [ content
83− [ props.theTip
84− , arrow
85− ]
86− ]
87− ]
88− ]
89− animatePresence = Motion.animatePresence </ { initial: false }
90− content =
91− Motion.div
92− </* { className: "popper-element-content"
93− , css: Style.content props
94− , initial: Motion.initial $ R.css { opacity: [ 1.0, 0.8, 0.0 ], scale: [ 1.0, 0.85 ] }
95− , animate: Motion.animate $ R.css { opacity: [ 0.0, 0.3, 1.0 ], scale: [ 0.0, 1.05, 1.0, 0.98, 1.01, 1.0 ] }
96− , exit: Motion.exit $ R.css { opacity: [ 1.0, 0.8, 0.0 ], scale: [ 1.0, 0.85 ] }
97− , transition: Motion.transition { duration: 0.2 }
98− , key: "container"
99− }
100− popperEl =
101− div
102− </* { className: "popper-element"
103− , css: Style.popper
104− , ref: unsafeCoerce (mkEffectFn1 setPopperElement)
105− , style: styles.popper
106− , _data: attributes.popper
107− }
108− arrow =
109− div
110− </*> { className: "popper-arrow"
111− , id: "arrow"
112− , css: Style.arrow props
113− , ref: unsafeCoerce (mkEffectFn1 setArrowElement)
114− , style: styles.arrow
115− , _data: attributes.arrow
116− }
117− refElem =
118− Motion.div
119− </ { ref: unsafeCoerce (mkEffectFn1 setReferenceElement)
120− , style: css { display: "inline-block" }
121− , onHoverStart: Motion.onHoverStart \_ _ -> hoveredIn
122− , onHoverEnd: Motion.onHoverEnd \_ _ -> hoveredOut
123− , onTouchStart: handler_ touchStarted
124− , onTouchEnd: handler_ touchEnded
125− }
126− pure result
src/Yoga/Block/Container/Style.js+24−14
@@ -3,25 +3,35 @@
33// So we just pretend nothing every matches
44// And never invoke the listeners
55const stubMatchMedia = () => {
6− if (window.matchMedia) return
7− window.matchMedia = (name) =>
8− ({
9− matches: false,
10− addEventListener: () => { },
11− removeEventListener: () => { }
12− })
6+ if (window.matchMedia) return
7+ window.matchMedia = (name) => ({
8+ matches: false,
9+ addEventListener: () => {},
10+ removeEventListener: () => {}
11+ })
1312}
1413
15−
16−exports.getComputedStyleImpl = (el, window) => window.getComputedStyle(el)
17−exports.getPropertyValueImpl = (propName, computedStyle) => computedStyle.getPropertyValue(propName)
18−exports.getElementStyle = el => () => el.style
19−exports.setStyleProperty = prop => value => style => () => style.setProperty(prop, value)
20−exports.matchMedia = string => window => () => {
14+export function getComputedStyleImpl(el, window) {
15+ return window.getComputedStyle(el)
16+}
17+export function getPropertyValueImpl(propName, computedStyle) {
18+ return computedStyle.getPropertyValue(propName)
19+}
20+export function getElementStyle(el) {
21+ return () => el.style
22+}
23+export function setStyleProperty(prop) {
24+ return (value) => (style) => () => style.setProperty(prop, value)
25+}
26+export function matchMedia(string) {
27+ return (window) => () => {
2128 stubMatchMedia()
2229 return window.matchMedia(string)
30+ }
2331}
24−exports.matches = matchMedia => () => {
32+export function matches(matchMedia) {
33+ return () => {
2534 stubMatchMedia()
2635 return matchMedia.matches
36+ }
2737}
src/Yoga/Block/Container/Style.purs+102−102
@@ -131,9 +131,9 @@ mkGlobal maybeMode =
131131 , margin: str "0"
132132 }
133133 <> case maybeMode of
134− Nothing → autoSwitchColourTheme
135− Just DarkMode → darkModeStyle
136− Just LightMode → lightModeStyle
134+ Nothing → autoSwitchColourTheme
135+ Just DarkMode → darkModeStyle
136+ Just LightMode → lightModeStyle
137137 , "pre,code":
138138 nest
139139 { fontFamily: str "var(--mono-font)"
@@ -390,73 +390,73 @@ defaultColours =
390390
391391 boxShadowDark = Color.rgba 0 0 0 0.6
392392
393−type FlatTheme a
394− = { background ∷ a
395− , popperBackground ∷ a
396− , popperBackgroundNoAlpha ∷ a
397− , popperInnerBorder ∷ a
398− , popperOuterBorder ∷ a
399− , backgroundAlpha0 ∷ a
400− , backgroundAlpha25 ∷ a
401− , backgroundAlpha50 ∷ a
402− , backgroundAlpha75 ∷ a
403− , backgroundLayer1 ∷ a
404− , backgroundLayer2 ∷ a
405− , backgroundLayer3 ∷ a
406− , backgroundLayer4 ∷ a
407− , backgroundLayer5 ∷ a
408− , backgroundLayer5Border ∷ a
409− , backgroundInverted ∷ a
410− , backgroundCard ∷ a
411− , interfaceBackground ∷ a
412− , interfaceBackgroundDangerous ∷ a
413− , interfaceDangerousText ∷ a
414− , interfaceBackgroundDisabled ∷ a
415− , interfaceTextDisabled ∷ a
416− , interfaceBackgroundHighlight ∷ a
417− , interfaceBackgroundShadow ∷ a
418− , inputBackground ∷ a
419− , inputBorder ∷ a
420− , link ∷ a
421− , highlight ∷ a
422− , highlightAlpha25 ∷ a
423− , highlightAlpha50 ∷ a
424− , highlightAlpha67 ∷ a
425− , highlightRotatedBackwards ∷ a
426− , highlightRotatedForwards ∷ a
427− , highlightDarker ∷ a
428− , highlightLighter ∷ a
429− , highlightDisabled ∷ a
430− , highlightText ∷ a
431− , success ∷ a
432− , successText ∷ a
433− , invalid ∷ a
434− , invalidText ∷ a
435− , required ∷ a
436− , text ∷ a
437− , textPaler1 ∷ a
438− , textPaler2 ∷ a
439− , textPaler3 ∷ a
440− , textPaler4 ∷ a
441− , textInverted ∷ a
442− , textInvertedPaler1 ∷ a
443− , textInvertedPaler2 ∷ a
444− , textInvertedPaler3 ∷ a
445− , textInvertedPaler4 ∷ a
446− , placeholderText ∷ a
447− , boxShadow ∷ a
448− }
393+type FlatTheme a =
394+ { background ∷ a
395+ , popperBackground ∷ a
396+ , popperBackgroundNoAlpha ∷ a
397+ , popperInnerBorder ∷ a
398+ , popperOuterBorder ∷ a
399+ , backgroundAlpha0 ∷ a
400+ , backgroundAlpha25 ∷ a
401+ , backgroundAlpha50 ∷ a
402+ , backgroundAlpha75 ∷ a
403+ , backgroundLayer1 ∷ a
404+ , backgroundLayer2 ∷ a
405+ , backgroundLayer3 ∷ a
406+ , backgroundLayer4 ∷ a
407+ , backgroundLayer5 ∷ a
408+ , backgroundLayer5Border ∷ a
409+ , backgroundInverted ∷ a
410+ , backgroundCard ∷ a
411+ , interfaceBackground ∷ a
412+ , interfaceBackgroundDangerous ∷ a
413+ , interfaceDangerousText ∷ a
414+ , interfaceBackgroundDisabled ∷ a
415+ , interfaceTextDisabled ∷ a
416+ , interfaceBackgroundHighlight ∷ a
417+ , interfaceBackgroundShadow ∷ a
418+ , inputBackground ∷ a
419+ , inputBorder ∷ a
420+ , link ∷ a
421+ , highlight ∷ a
422+ , highlightAlpha25 ∷ a
423+ , highlightAlpha50 ∷ a
424+ , highlightAlpha67 ∷ a
425+ , highlightRotatedBackwards ∷ a
426+ , highlightRotatedForwards ∷ a
427+ , highlightDarker ∷ a
428+ , highlightLighter ∷ a
429+ , highlightDisabled ∷ a
430+ , highlightText ∷ a
431+ , success ∷ a
432+ , successText ∷ a
433+ , invalid ∷ a
434+ , invalidText ∷ a
435+ , required ∷ a
436+ , text ∷ a
437+ , textPaler1 ∷ a
438+ , textPaler2 ∷ a
439+ , textPaler3 ∷ a
440+ , textPaler4 ∷ a
441+ , textInverted ∷ a
442+ , textInvertedPaler1 ∷ a
443+ , textInvertedPaler2 ∷ a
444+ , textInvertedPaler3 ∷ a
445+ , textInvertedPaler4 ∷ a
446+ , placeholderText ∷ a
447+ , boxShadow ∷ a
448+ }
449449
450−type Colours
451− = { dark ∷ FlatTheme Color
452− , light ∷ FlatTheme Color
453− }
450+type Colours =
451+ { dark ∷ FlatTheme Color
452+ , light ∷ FlatTheme Color
453+ }
454454
455−data MakeCSSVarLabels
456− = MakeCSSVarLabels
455+data MakeCSSVarLabels = MakeCSSVarLabels
457456
458457instance makeCSSVarLabels' ∷
459− (IsSymbol sym) ⇒
458+ ( IsSymbol sym
459+ ) ⇒
460460 MappingWithIndex MakeCSSVarLabels (Proxy sym) a String where
461461 mappingWithIndex MakeCSSVarLabels prop _ = "--" <> (reflectSymbol prop)
462462
@@ -525,34 +525,34 @@ variables =
525525 , "--theme-variant": str "light"
526526 }
527527
528−type Sizes
529− = { "3xl" ∷ String
530− , "3xs" ∷ String
531− , "4xl" ∷ String
532− , "4xs" ∷ String
533− , "5xl" ∷ String
534− , "5xs" ∷ String
535− , l ∷ String
536− , m ∷ String
537− , s ∷ String
538− , text ∷
539− { interactive ∷ String
540− , label ∷ String
541− , copy ∷ String
542− , small ∷ String
543− , tiny ∷ String
544− , heading ∷
545− { h1 ∷ String
546− , h2 ∷ String
547− , h3 ∷ String
548− , h4 ∷ String
549− }
550− }
551− , xl ∷ String
552− , xs ∷ String
553− , xxl ∷ String
554− , xxs ∷ String
555− }
528+type Sizes =
529+ { "3xl" ∷ String
530+ , "3xs" ∷ String
531+ , "4xl" ∷ String
532+ , "4xs" ∷ String
533+ , "5xl" ∷ String
534+ , "5xs" ∷ String
535+ , l ∷ String
536+ , m ∷ String
537+ , s ∷ String
538+ , text ∷
539+ { interactive ∷ String
540+ , label ∷ String
541+ , copy ∷ String
542+ , small ∷ String
543+ , tiny ∷ String
544+ , heading ∷
545+ { h1 ∷ String
546+ , h2 ∷ String
547+ , h3 ∷ String
548+ , h4 ∷ String
549+ }
550+ }
551+ , xl ∷ String
552+ , xs ∷ String
553+ , xxl ∷ String
554+ , xxs ∷ String
555+ }
556556
557557size ∷ Sizes
558558size =
@@ -584,14 +584,14 @@ size =
584584 }
585585 }
586586
587−type BoxShadows
588− = { s ∷ String
589− , m ∷ String
590− , l ∷ String
591− , xl ∷ String
592− , xxl ∷ String
593− , default ∷ String
594− }
587+type BoxShadows =
588+ { s ∷ String
589+ , m ∷ String
590+ , l ∷ String
591+ , xl ∷ String
592+ , xxl ∷ String
593+ , default ∷ String
594+ }
595595
596596boxShadow ∷ BoxShadows
597597boxShadow =
src/Yoga/Block/Hook/Key.js+7−7
@@ -1,7 +1,7 @@
1−exports.getKeyImpl = function (just) {
2− return function (nothing) {
3− return function (event) {
4− return event.keyCode ? just(event.keyCode) : nothing;
5− };
6− };
7−};
1+export function getKeyImpl(just) {
2+ return function (nothing) {
3+ return function (event) {
4+ return event.keyCode ? just(event.keyCode) : nothing
5+ }
6+ }
7+}
src/Yoga/Block/Hook/UseInView.js+2−2
@@ -1,3 +1,3 @@
1−const reactIntersectionObserver = require("react-intersection-observer")
1+import { useInView } from "react-intersection-observer"
22
3−exports.useInViewImpl = reactIntersectionObserver.useInView
3+export const useInViewImpl = useInView
src/Yoga/Block/Hook/UseResize.purs+10−9
@@ -1,16 +1,17 @@
11module Yoga.Block.Hook.UseResize where
22
33import Prelude
4+
45import Data.Foldable (for_)
56import Data.Int (toNumber)
67import Data.Maybe (Maybe(..))
78import Data.Newtype (class Newtype)
9+import Data.Ord (abs)
810import Data.Time.Duration (class Duration)
911import Data.Time.Duration as Milliseconds
1012import Effect (Effect)
1113import Effect.Aff (Aff, Fiber, delay, error, killFiber, launchAff, launchAff_)
1214import Effect.Class (liftEffect)
13−import Math as Math
1415import React.Basic.Hooks (Hook, UseLayoutEffect, UseState, coerceHook, useLayoutEffect, useLayoutEffectOnce, (/\))
1516import React.Basic.Hooks as React
1617import Web.Event.Event (EventType(..))
@@ -65,12 +66,12 @@ newtype UseOnResize hooks = UseOnResize
6566
6667derive instance ntUseOnResize ∷ Newtype (UseOnResize hooks) _
6768
68−useOnResize ∷
69− ∀ d.
70− Duration d =>
71− d ->
72− ({ innerWidth ∷ Number, innerHeight ∷ Number, deltaWidth ∷ Number, deltaHeight ∷ Number } -> Effect Unit) ->
73− Hook UseOnResize Unit
69+useOnResize
70+ ∷ ∀ d
71+ . Duration d
72+ => d
73+ -> ({ innerWidth ∷ Number, innerHeight ∷ Number, deltaWidth ∷ Number, deltaHeight ∷ Number } -> Effect Unit)
74+ -> Hook UseOnResize Unit
7475useOnResize debounceBy callback =
7576 coerceHook React.do
7677 mbFiber /\ setFiber <- React.useState' Nothing
@@ -87,8 +88,8 @@ useOnResize debounceBy callback =
8788 for_ mbFiber (killFiber (error "Fiber cancelled"))
8889 delay (Milliseconds.fromDuration debounceBy)
8990 let { innerWidth, innerHeight } = dimensions
90− let deltaWidth = Math.abs (size.innerWidth - innerWidth)
91− let deltaHeight = Math.abs (size.innerHeight - innerWidth)
91+ let deltaWidth = abs (size.innerWidth - innerWidth)
92+ let deltaHeight = abs (size.innerHeight - innerWidth)
9293 setSize dimensions # liftEffect
9394 callback { innerWidth, innerHeight, deltaWidth, deltaHeight } # liftEffect
9495 fiber ∷ Fiber _ <- launchAff aff
src/Yoga/Block/Internal.js+53−39
@@ -1,54 +1,68 @@
1−const React = require("react")
2−
3−exports.mkForwardRefComponent = (displayName) => (renderFn) => {
4− const component = (props, ref) => renderFn(props)(ref)();
5− component.displayName = displayName;
6− component.whyDidYouRender = true;
7− return React.forwardRef(component);
8−};
1+import { forwardRef, createRef as _createRef } from "react"
92
3+export function mkForwardRefComponent(displayName) {
4+ return (renderFn) => {
5+ const component = (props, ref) => renderFn(props)(ref)()
6+ component.displayName = displayName
7+ component.whyDidYouRender = true
8+ return forwardRef(component)
9+ }
10+}
1011
11−exports.mkForwardRefComponentEffect = (displayName) => (renderFn) => () => {
12− const component = (props, ref) => renderFn(props)(ref)();
13− component.displayName = displayName;
14− return React.forwardRef(component);
15−};
12+export function mkForwardRefComponentEffect(displayName) {
13+ return (renderFn) => () => {
14+ const component = (props, ref) => renderFn(props)(ref)()
15+ component.displayName = displayName
16+ return forwardRef(component)
17+ }
18+}
1619
17−exports.pickDefinedFn = function (ref, ks, obj) {
18− const copy = {}
19− for (let i = 0; i < ks.length; i++) {
20− if (obj[ks[i]] !== undefined) {
21− copy[ks[i]] = obj[ks[i]];
22− }
23− }
24− if (ref !== undefined) {
25− copy.ref = ref
20+export function pickDefinedFn(ref, ks, obj) {
21+ const copy = {}
22+ for (let i = 0; i < ks.length; i++) {
23+ if (obj[ks[i]] !== undefined) {
24+ copy[ks[i]] = obj[ks[i]]
2625 }
27− return copy;
28−};
26+ }
27+ if (ref !== undefined) {
28+ copy.ref = ref
29+ }
30+ return copy
31+}
2932
30−exports.createRef = React.createRef
33+export const createRef = _createRef
3134
32−exports.unsafeMergeSecond = (r1) => (r2) => {
35+export function unsafeMergeSecond(r1) {
36+ return (r2) => {
3337 for (var k1 in r2) {
34− if ({}.hasOwnProperty.call(r2, k1) && r2[k1] !== undefined) {
35− r1[k1] = r2[k1];
36− }
38+ if ({}.hasOwnProperty.call(r2, k1) && r2[k1] !== undefined) {
39+ r1[k1] = r2[k1]
40+ }
3741 }
3842 return r1
43+ }
3944}
4045
41−exports.unsafeUnionDroppingUndefined = (r1) => (r2) => {
42− var copy = {};
46+export function unsafeUnionDroppingUndefined(r1) {
47+ return (r2) => {
48+ var copy = {}
4349 for (var k1 in r2) {
44− if ({}.hasOwnProperty.call(r2, k1) && r2[k1] !== undefined) {
45− copy[k1] = r2[k1];
46− }
50+ if ({}.hasOwnProperty.call(r2, k1) && r2[k1] !== undefined) {
51+ copy[k1] = r2[k1]
52+ }
4753 }
4854 for (var k2 in r1) {
49− if ({}.hasOwnProperty.call(r1, k2) && r1[k2] !== undefined) {
50− copy[k2] = r1[k2];
51− }
55+ if ({}.hasOwnProperty.call(r1, k2) && r1[k2] !== undefined) {
56+ copy[k2] = r1[k2]
57+ }
5258 }
53− return copy;
54−}
59+ return copy
60+ }
61+}
62+
63+export function deleteUndefineds(obj) {
64+ Object.keys(obj).forEach((key) =>
65+ obj[key] === undefined ? delete obj[key] : {}
66+ )
67+ return obj
68+}
src/Yoga/Block/Internal.purs+549−552
@@ -5,6 +5,7 @@ module Yoga.Block.Internal
55 , unsafeEmotion
66 , unsafeDiv
77 , dangerous
8+ , deleteUndefineds
89 , DivProps
910 , DivPropsF
1011 , DivPropsNoChildren
@@ -27,6 +28,7 @@ module Yoga.Block.Internal
2728 , module Yoga.Block.Internal.CSS
2829 , unsafeUnionDroppingUndefined
2930 , unsafeMergeSecond
31+ , unsafeAddProps
3032 , createRef
3133 , getBoundingBoxFromRef
3234 , getElementFromRef
@@ -62,37 +64,40 @@ import React.Basic.Emotion as E
6264import React.Basic.Events (EventHandler)
6365import React.Basic.Hooks (JSX, ReactComponent, Ref, Render, readRefMaybe)
6466import Record.Extra (class Keys, keys)
65−import Type.Data.Row (RProxy(..))
67+import Type.Proxy (Proxy(..))
6668import Unsafe.Coerce (unsafeCoerce)
6769import Untagged.Union (UndefinedOr, uorToMaybe)
6870import Web.DOM (Element, Node)
69−import Web.DOM.Element (scrollHeight, scrollWidth)
71+import Web.DOM.Element (scrollHeight, scrollWidth, DOMRect, getBoundingClientRect)
7072import Web.DOM.Element as Element
7173import Web.DOM.NonElementParentNode (getElementById)
7274import Web.HTML (window)
7375import Web.HTML.HTMLDocument as HTMLDocument
74−import Web.HTML.HTMLElement (DOMRect, HTMLElement, focus, getBoundingClientRect, offsetHeight, offsetWidth)
76+import Web.HTML.HTMLElement (HTMLElement, focus, offsetHeight, offsetWidth)
7577import Web.HTML.HTMLElement as HTMLElement
7678import Web.HTML.Window (document)
7779import Yoga.Block.Internal.CSS (_0)
7880import Yoga.Block.Internal.OptionalProp (OptionalProp(..), Id, appendIfDefined, asOptional, composeHandler, getOr, getOrFlipped, ifTrue, isTruthy, maybeToOp, opToMaybe, setOrDelete, unsafeUnMaybe, unsafeUnOptional, (<>?), (?||))
81+import Record.Unsafe.Union (unsafeUnion)
7982
80−foreign import mkForwardRefComponent ∷
81− ∀ inputProps props a hooks.
82− String ->
83− ({ | inputProps } -> Ref a -> Render Unit hooks JSX) ->
84− ReactComponent { | props }
83+unsafeAddProps ∷ ∀ r s. { | r } → { | s } → { | r }
84+unsafeAddProps = unsafeUnion
8585
86−foreign import mkForwardRefComponentEffect ∷
87− ∀ inputProps props a hooks.
88− String ->
89− ({ | inputProps } -> Ref a -> Render Unit hooks JSX) ->
90− Effect (ReactComponent { | props })
86+foreign import mkForwardRefComponent
87+ ∷ ∀ inputProps props a hooks
88+ . String
89+ -> ({ | inputProps } -> Ref a -> Render Unit hooks JSX)
90+ -> ReactComponent { | props }
91+
92+foreign import mkForwardRefComponentEffect
93+ ∷ ∀ inputProps props a hooks
94+ . String
95+ -> ({ | inputProps } -> Ref a -> Render Unit hooks JSX)
96+ -> Effect (ReactComponent { | props })
9197
9298foreign import createRef ∷ ∀ a. Effect (Ref a)
9399
94−type NodeRef
95− = Ref (Nullable Node)
100+type NodeRef = Ref (Nullable Node)
96101
97102focusNodeRef ∷ NodeRef -> Effect Unit
98103focusNodeRef ref = do
@@ -108,8 +113,8 @@ findElementByIdInDocument id = do
108113
109114getBoundingBoxFromRef ∷ NodeRef -> Effect (Maybe DOMRect)
110115getBoundingBoxFromRef itemRef = do
111− htmlElem <- getHTMLElementFromRef itemRef
112− for htmlElem getBoundingClientRect
116+ elem <- getElementFromRef itemRef
117+ for elem getBoundingClientRect
113118
114119getOffsetWidthFromRef ∷ NodeRef -> Effect (Maybe Number)
115120getOffsetWidthFromRef itemRef = do
@@ -169,34 +174,36 @@ forwardedRefAsMaybe r = safelyWrapped # uorToMaybe >>= Nullable.toMaybe
169174
170175foreign import unsafeUnionDroppingUndefined ∷ ∀ r1 r2 r3. Record r1 -> Record r2 -> Record r3
171176
177+foreign import deleteUndefineds ∷ ∀ r. Record r -> Record r
178+
172179foreign import unsafeMergeSecond ∷ ∀ r1 r2 r3. Record r1 -> Record r2 -> Record r3
173180
174181unsafeEmotion ∷ ∀ props propsA propsB. ReactComponent { className ∷ String, css ∷ E.Style | props } -> Record propsA -> { className ∷ String, css ∷ E.Style | propsB } -> JSX
175182unsafeEmotion component propsA propsB = E.element component (unsafeUnionDroppingUndefined propsB propsA)
176183
177−emotionDiv_ ∷
178− ∀ props props_.
179− Lacks "ref" props =>
180− Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | DivProps ) =>
181− (Record (DivProps)) ->
182− { className ∷ String
183− , css ∷ Style
184− | props
185− } ->
186− JSX
184+emotionDiv_
185+ ∷ ∀ props props_
186+ . Lacks "ref" props
187+ => Union props props_ (className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | DivProps)
188+ => (Record (DivProps))
189+ -> { className ∷ String
190+ , css ∷ Style
191+ | props
192+ }
193+ -> JSX
187194emotionDiv_ = unsafeEmotion unsafeDiv
188195
189−emotionDiv ∷
190− ∀ props props_ more.
191− Lacks "ref" props =>
192− Union props props_ ( className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | DivProps ) =>
193− Ref (Nullable Node) ->
194− { | DivPropsF Id more } ->
195− { className ∷ String
196− , css ∷ Style
197− | props
198− } ->
199− JSX
196+emotionDiv
197+ ∷ ∀ props props_ more
198+ . Lacks "ref" props
199+ => Union props props_ (className ∷ String, css ∷ Style, ref ∷ Ref (Nullable Node) | DivProps)
200+ => Ref (Nullable Node)
201+ -> { | DivPropsF Id more }
202+ -> { className ∷ String
203+ , css ∷ Style
204+ | props
205+ }
206+ -> JSX
200207emotionDiv ref = emotionDiv_ <<< pickDefined ref
201208
202209unsafeDiv ∷ ∀ r. ReactComponent (Record r)
@@ -204,39 +211,39 @@ unsafeDiv = dangerous "div"
204211
205212foreign import pickDefinedFn ∷ ∀ r1 r2. Fn3 (Ref (Nullable Node)) (Array String) (Record r1) (Record r2)
206213
207−pickDefined ∷
208− ∀ a r b l.
209− Row.Union b r a =>
210− RL.RowToList b l =>
211− Ref (Nullable Node) ->
212− Keys l =>
213− Record a ->
214− { ref ∷ Ref (Nullable Node) | b }
214+pickDefined
215+ ∷ ∀ a r b l
216+ . Row.Union b r a
217+ => RL.RowToList b l
218+ => Ref (Nullable Node)
219+ -> Keys l
220+ => Record a
221+ -> { ref ∷ Ref (Nullable Node) | b }
215222pickDefined ref = runFn3 pickDefinedFn ref ks
216223 where
217− ks = Array.fromFoldable $ keys (RProxy ∷ RProxy b)
218−
219−emotionInput_ ∷
220− ∀ props props_.
221− Union props props_ ( className ∷ String, css ∷ Style | InputWritablePropsF Id () ) =>
222− { | InputWritableProps } ->
223− { className ∷ String
224− , css ∷ Style
225− | props
226− } ->
227− JSX
224+ ks = Array.fromFoldable $ keys (Proxy ∷ Proxy b)
225+
226+emotionInput_
227+ ∷ ∀ props props_
228+ . Union props props_ (className ∷ String, css ∷ Style | InputWritablePropsF Id ())
229+ => { | InputWritableProps }
230+ -> { className ∷ String
231+ , css ∷ Style
232+ | props
233+ }
234+ -> JSX
228235emotionInput_ = unsafeEmotion unsafeInput
229236
230−emotionInput ∷
231− ∀ props props_ more.
232− Union props props_ ( className ∷ String, css ∷ Style | InputWritableProps ) =>
233− Ref (Nullable Node) ->
234− { | InputReadablePropsF OptionalProp more } ->
235− { className ∷ String
236− , css ∷ Style
237− | props
238− } ->
239− JSX
237+emotionInput
238+ ∷ ∀ props props_ more
239+ . Union props props_ (className ∷ String, css ∷ Style | InputWritableProps)
240+ => Ref (Nullable Node)
241+ -> { | InputReadablePropsF OptionalProp more }
242+ -> { className ∷ String
243+ , css ∷ Style
244+ | props
245+ }
246+ -> JSX
240247emotionInput ref = emotionInput_ <<< pickDefined ref <<< coerceUnOptional
241248 where
242249 coerceUnOptional ∷ { | InputReadablePropsF OptionalProp more } -> { | InputReadablePropsF Id more }
@@ -245,28 +252,28 @@ emotionInput ref = emotionInput_ <<< pickDefined ref <<< coerceUnOptional
245252unsafeInput ∷ ∀ r. ReactComponent (Record r)
246253unsafeInput = dangerous "input"
247254
248−emotionButton_ ∷
249− ∀ props props_.
250− Union props props_ ( className ∷ String, css ∷ Style | ButtonWritableProps ) =>
251− { | ButtonWritableProps } ->
252− { className ∷ String
253− , css ∷ Style
254− | props
255− } ->
256− JSX
255+emotionButton_
256+ ∷ ∀ props props_
257+ . Union props props_ (className ∷ String, css ∷ Style | ButtonWritableProps)
258+ => { | ButtonWritableProps }
259+ -> { className ∷ String
260+ , css ∷ Style
261+ | props
262+ }
263+ -> JSX
257264emotionButton_ = unsafeEmotion unsafeButton
258265
259−emotionButton ∷
260− ∀ props props_ more.
261− Lacks "ref" props =>
262− Union props props_ ( className ∷ String, css ∷ Style | ButtonWritableProps ) =>
263− Ref (Nullable Node) ->
264− { | ButtonReadablePropsF OptionalProp more } ->
265− { className ∷ String
266− , css ∷ Style
267− | props
268− } ->
269− JSX
266+emotionButton
267+ ∷ ∀ props props_ more
268+ . Lacks "ref" props
269+ => Union props props_ (className ∷ String, css ∷ Style | ButtonWritableProps)
270+ => Ref (Nullable Node)
271+ -> { | ButtonReadablePropsF OptionalProp more }
272+ -> { className ∷ String
273+ , css ∷ Style
274+ | props
275+ }
276+ -> JSX
270277emotionButton ref = emotionButton_ <<< pickDefined ref <<< coerceUnOptional
271278 where
272279 coerceUnOptional ∷ { | ButtonReadablePropsF OptionalProp more } -> { | ButtonReadablePropsF Id more }
@@ -280,475 +287,465 @@ dangerous = unsafePerformEffect <<< unsafeCreateDOMComponent
280287
281288-- type DivProps =
282289-- Props_div
283−type DivProps
284− = DivPropsF Id ()
285−
286−type DivPropsNoChildren
287− = DivPropsNoChildrenF Id ()
288−
289−type DivPropsF f more
290− = DivPropsNoChildrenF f ( children ∷ f (Array JSX) | more)
291−
292−type DivPropsNoChildrenF f more
293− = ( _aria ∷ f (Object String)
294− , _data ∷ f (Object String)
295− , about ∷ f String
296− , acceptCharset ∷ f String
297− , accessKey ∷ f String
298− , allowFullScreen ∷ f Boolean
299− , autoFocus ∷ f Boolean
300− , autoPlay ∷ f Boolean
301− , capture ∷ f Boolean
302− , cellPadding ∷ f String
303− , cellSpacing ∷ f String
304− , charSet ∷ f String
305− , classID ∷ f String
306− , colSpan ∷ f Int
307− , contentEditable ∷ f Boolean
308− , contextMenu ∷ f String
309− , crossOrigin ∷ f String
310− , dangerouslySetInnerHTML ∷ f { __html ∷ f String }
311− , datatype ∷ f String
312− , dateTime ∷ f String
313− , dir ∷ f String
314− , draggable ∷ f Boolean
315− , encType ∷ f String
316− , formAction ∷ f String
317− , formEncType ∷ f String
318− , formMethod ∷ f String
319− , formNoValidate ∷ f Boolean
320− , formTarget ∷ f String
321− , frameBorder ∷ f String
322− , hidden ∷ f Boolean
323− , hrefLang ∷ f String
324− , htmlFor ∷ f String
325− , httpEquiv ∷ f String
326− , icon ∷ f String
327− , id ∷ f String
328− , inlist ∷ f String
329− , inputMode ∷ f String
330− , is ∷ f String
331− , itemID ∷ f String
332− , itemProp ∷ f String
333− , itemRef ∷ f String
334− , itemScope ∷ f Boolean
335− , itemType ∷ f String
336− , keyParams ∷ f String
337− , keyType ∷ f String
338− , lang ∷ f String
339− , marginHeight ∷ f String
340− , marginWidth ∷ f String
341− , maxLength ∷ f Int
342− , mediaGroup ∷ f String
343− , minLength ∷ f Int
344− , noValidate ∷ f Boolean
345− , onAnimationEnd ∷ f EventHandler
346− , onAnimationIteration ∷ f EventHandler
347− , onAnimationStart ∷ f EventHandler
348− , onBlur ∷ f EventHandler
349− , onClick ∷ f EventHandler
350− , onCompositionEnd ∷ f EventHandler
351− , onCompositionStart ∷ f EventHandler
352− , onCompositionUpdate ∷ f EventHandler
353− , onContextMenu ∷ f EventHandler
354− , onCopy ∷ f EventHandler
355− , onCut ∷ f EventHandler
356− , onDoubleClick ∷ f EventHandler
357− , onDrag ∷ f EventHandler
358− , onDragEnd ∷ f EventHandler
359− , onDragEnter ∷ f EventHandler
360− , onDragExit ∷ f EventHandler
361− , onDragLeave ∷ f EventHandler
362− , onDragOver ∷ f EventHandler
363− , onDragStart ∷ f EventHandler
364− , onDrop ∷ f EventHandler
365− , onFocus ∷ f EventHandler
366− , onGotPointerCapture ∷ f EventHandler
367− , onInvalid ∷ f EventHandler
368− , onKeyDown ∷ f EventHandler
369− , onKeyPress ∷ f EventHandler
370− , onKeyUp ∷ f EventHandler
371− , onLostPointerCapture ∷ f EventHandler
372− , onMouseDown ∷ f EventHandler
373− , onMouseEnter ∷ f EventHandler
374− , onMouseLeave ∷ f EventHandler
375− , onMouseMove ∷ f EventHandler
376− , onMouseOut ∷ f EventHandler
377− , onMouseOver ∷ f EventHandler
378− , onMouseUp ∷ f EventHandler
379− , onPaste ∷ f EventHandler
380− , onPointerCancel ∷ f EventHandler
381− , onPointerDown ∷ f EventHandler
382− , onPointerEnter ∷ f EventHandler
383− , onPointerLeave ∷ f EventHandler
384− , onPointerMove ∷ f EventHandler
385− , onPointerOut ∷ f EventHandler
386− , onPointerOver ∷ f EventHandler
387− , onPointerUp ∷ f EventHandler
388− , onSelect ∷ f EventHandler
389− , onSubmit ∷ f EventHandler
390− , onTouchCancel ∷ f EventHandler
391− , onTouchEnd ∷ f EventHandler
392− , onTouchMove ∷ f EventHandler
393− , onTouchStart ∷ f EventHandler
394− , onTransitionEnd ∷ f EventHandler
395− , onWheel ∷ f EventHandler
396− , prefix ∷ f String
397− , property ∷ f String
398− , radioGroup ∷ f String
399− , readOnly ∷ f Boolean
400− , ref ∷ f (Ref (Nullable Node))
401− , resource ∷ f String
402− , role ∷ f String
403− , rowSpan ∷ f Int
404− , scoped ∷ f Boolean
405− , seamless ∷ f Boolean
406− , security ∷ f String
407− , spellCheck ∷ f Boolean
408− , srcDoc ∷ f JSX
409− , srcLang ∷ f String
410− , srcSet ∷ f String
411− , style ∷ f CSS
412− , suppressContentEditableWarning ∷ f Boolean
413− , tabIndex ∷ f Int
414− , title ∷ f String
415− , typeof ∷ f String
416− , unselectable ∷ f Boolean
417− , useMap ∷ f String
418− , vocab ∷ f String
419− , wmode ∷ f String
420− | more
421− )
422−type InputReadableProps
423− = InputReadablePropsF OptionalProp ()
424−
425−type InputWritableProps
426− = InputWritablePropsF Id ()
427−
428−type InputWritablePropsF f more
429− = InputReadablePropsF f
430− ( ref ∷ f (Ref (Nullable Node))
431− | more
432− )
433−
434−type InputReadablePropsF f more
435− = ( _aria ∷ f (Object String)
436− , _data ∷ f (Object String)
437− , about ∷ f String
438− , accept ∷ f String
439− , acceptCharset ∷ f String
440− , accessKey ∷ f String
441− , allowFullScreen ∷ f Boolean
442− , alt ∷ f String
443− , autoCapitalize ∷ f String
444− , autoComplete ∷ f String
445− , autoCorrect ∷ f String
446− , autoFocus ∷ f Boolean
447− , autoPlay ∷ f Boolean
448− , autoSave ∷ f String
449− , capture ∷ f Boolean
450− , cellPadding ∷ f String
451− , cellSpacing ∷ f String
452− , charSet ∷ f String
453− , checked ∷ f Boolean
454− , classID ∷ f String
455− , colSpan ∷ f Int
456− , contentEditable ∷ f Boolean
457− , contextMenu ∷ f String
458− , crossOrigin ∷ f String
459− , dangerouslySetInnerHTML ∷ f { __html ∷ f String }
460− , datatype ∷ f String
461− , dateTime ∷ f String
462− , defaultChecked ∷ f String
463− , defaultValue ∷ f String
464− , dir ∷ f String
465− , disabled ∷ f Boolean
466− , draggable ∷ f Boolean
467− , encType ∷ f String
468− , form ∷ f String
469− , formAction ∷ f String
470− , formEncType ∷ f String
471− , formMethod ∷ f String
472− , formNoValidate ∷ f Boolean
473− , formTarget ∷ f String
474− , frameBorder ∷ f String
475− , height ∷ f String
476− , hidden ∷ f Boolean
477− , hrefLang ∷ f String
478− , htmlFor ∷ f String
479− , httpEquiv ∷ f String
480− , icon ∷ f String
481− , id ∷ f String
482− , inlist ∷ f String
483− , inputMode ∷ f String
484− , is ∷ f String
485− , itemID ∷ f String
486− , itemProp ∷ f String
487− , itemRef ∷ f String
488− , itemScope ∷ f Boolean
489− , itemType ∷ f String
490− , keyParams ∷ f String
491− , keyType ∷ f String
492− , lang ∷ f String
493− , list ∷ f String
494− , marginHeight ∷ f String
495− , marginWidth ∷ f String
496− , maxLength ∷ f Int
497− , mediaGroup ∷ f String
498− , minLength ∷ f Int
499− , multiple ∷ f Boolean
500− , name ∷ f String
501− , noValidate ∷ f Boolean
502− , onAnimationEnd ∷ f EventHandler
503− , onAnimationIteration ∷ f EventHandler
504− , onAnimationStart ∷ f EventHandler
505− , onBlur ∷ f EventHandler
506− , onChange ∷ f EventHandler
507− , onClick ∷ f EventHandler
508− , onCompositionEnd ∷ f EventHandler
509− , onCompositionStart ∷ f EventHandler
510− , onCompositionUpdate ∷ f EventHandler
511− , onContextMenu ∷ f EventHandler
512− , onCopy ∷ f EventHandler
513− , onCut ∷ f EventHandler
514− , onDoubleClick ∷ f EventHandler
515− , onDrag ∷ f EventHandler
516− , onDragEnd ∷ f EventHandler
517− , onDragEnter ∷ f EventHandler
518− , onDragExit ∷ f EventHandler
519− , onDragLeave ∷ f EventHandler
520− , onDragOver ∷ f EventHandler
521− , onDragStart ∷ f EventHandler
522− , onDrop ∷ f EventHandler
523− , onFocus ∷ f EventHandler
524− , onGotPointerCapture ∷ f EventHandler
525− , onInvalid ∷ f EventHandler
526− , onKeyDown ∷ f EventHandler
527− , onKeyPress ∷ f EventHandler
528− , onKeyUp ∷ f EventHandler
529− , onLostPointerCapture ∷ f EventHandler
530− , onMouseDown ∷ f EventHandler
531− , onMouseEnter ∷ f EventHandler
532− , onMouseLeave ∷ f EventHandler
533− , onMouseMove ∷ f EventHandler
534− , onMouseOut ∷ f EventHandler
535− , onMouseOver ∷ f EventHandler
536− , onMouseUp ∷ f EventHandler
537− , onPaste ∷ f EventHandler
538− , onPointerCancel ∷ f EventHandler
539− , onPointerDown ∷ f EventHandler
540− , onPointerEnter ∷ f EventHandler
541− , onPointerLeave ∷ f EventHandler
542− , onPointerMove ∷ f EventHandler
543− , onPointerOut ∷ f EventHandler
544− , onPointerOver ∷ f EventHandler
545− , onPointerUp ∷ f EventHandler
546− , onSelect ∷ f EventHandler
547− , onSubmit ∷ f EventHandler
548− , onTouchCancel ∷ f EventHandler
549− , onTouchEnd ∷ f EventHandler
550− , onTouchMove ∷ f EventHandler
551− , onTouchStart ∷ f EventHandler
552− , onTransitionEnd ∷ f EventHandler
553− , onWheel ∷ f EventHandler
554− , pattern ∷ f String
555− , placeholder ∷ f String
556− , prefix ∷ f String
557− , property ∷ f String
558− , radioGroup ∷ f String
559− -- , ref ∷ f (Ref (Nullable Node))
560− , readOnly ∷ f Boolean
561− , required ∷ f Boolean
562− , resource ∷ f String
563− , results ∷ f String
564− , role ∷ f String
565− , rowSpan ∷ f Int
566− , scoped ∷ f Boolean
567− , seamless ∷ f Boolean
568− , security ∷ f String
569− , size ∷ f Int
570− , spellCheck ∷ f Boolean
571− , src ∷ f String
572− , srcDoc ∷ f JSX
573− , srcLang ∷ f String
574− , srcSet ∷ f String
575− , step ∷ f String
576− , style ∷ f CSS
577− , suppressContentEditableWarning ∷ f Boolean
578− , tabIndex ∷ f Int
579− , title ∷ f String
580− , type ∷ f String
581− , typeof ∷ f String
582− , unselectable ∷ f Boolean
583− , useMap ∷ f String
584− , value ∷ f String
585− , vocab ∷ f String
586− , width ∷ f String
587− , wmode ∷ f String
588− , min ∷ f (String)
589− , max ∷ f (String)
590− | more
591− )
592−
593−type ButtonReadableProps
594− = ButtonReadablePropsF OptionalProp ()
595−
596−type ButtonWritableProps
597− = ButtonWritablePropsF Id ()
290+type DivProps = DivPropsF Id ()
291+
292+type DivPropsNoChildren = DivPropsNoChildrenF Id ()
293+
294+type DivPropsF f more = DivPropsNoChildrenF f (children ∷ f (Array JSX) | more)
295+
296+type DivPropsNoChildrenF f more =
297+ ( _aria ∷ f (Object String)
298+ , _data ∷ f (Object String)
299+ , about ∷ f String
300+ , acceptCharset ∷ f String
301+ , accessKey ∷ f String
302+ , allowFullScreen ∷ f Boolean
303+ , autoFocus ∷ f Boolean
304+ , autoPlay ∷ f Boolean
305+ , capture ∷ f Boolean
306+ , cellPadding ∷ f String
307+ , cellSpacing ∷ f String
308+ , charSet ∷ f String
309+ , classID ∷ f String
310+ , colSpan ∷ f Int
311+ , contentEditable ∷ f Boolean
312+ , contextMenu ∷ f String
313+ , crossOrigin ∷ f String
314+ , dangerouslySetInnerHTML ∷ f { __html ∷ f String }
315+ , datatype ∷ f String
316+ , dateTime ∷ f String
317+ , dir ∷ f String
318+ , draggable ∷ f Boolean
319+ , encType ∷ f String
320+ , formAction ∷ f String
321+ , formEncType ∷ f String
322+ , formMethod ∷ f String
323+ , formNoValidate ∷ f Boolean
324+ , formTarget ∷ f String
325+ , frameBorder ∷ f String
326+ , hidden ∷ f Boolean
327+ , hrefLang ∷ f String
328+ , htmlFor ∷ f String
329+ , httpEquiv ∷ f String
330+ , icon ∷ f String
331+ , id ∷ f String
332+ , inlist ∷ f String
333+ , inputMode ∷ f String
334+ , is ∷ f String
335+ , itemID ∷ f String
336+ , itemProp ∷ f String
337+ , itemRef ∷ f String
338+ , itemScope ∷ f Boolean
339+ , itemType ∷ f String
340+ , keyParams ∷ f String
341+ , keyType ∷ f String
342+ , lang ∷ f String
343+ , marginHeight ∷ f String
344+ , marginWidth ∷ f String
345+ , maxLength ∷ f Int
346+ , mediaGroup ∷ f String
347+ , minLength ∷ f Int
348+ , noValidate ∷ f Boolean
349+ , onAnimationEnd ∷ f EventHandler
350+ , onAnimationIteration ∷ f EventHandler
351+ , onAnimationStart ∷ f EventHandler
352+ , onBlur ∷ f EventHandler
353+ , onClick ∷ f EventHandler
354+ , onCompositionEnd ∷ f EventHandler
355+ , onCompositionStart ∷ f EventHandler
356+ , onCompositionUpdate ∷ f EventHandler
357+ , onContextMenu ∷ f EventHandler
358+ , onCopy ∷ f EventHandler
359+ , onCut ∷ f EventHandler
360+ , onDoubleClick ∷ f EventHandler
361+ , onDrag ∷ f EventHandler
362+ , onDragEnd ∷ f EventHandler
363+ , onDragEnter ∷ f EventHandler
364+ , onDragExit ∷ f EventHandler
365+ , onDragLeave ∷ f EventHandler
366+ , onDragOver ∷ f EventHandler
367+ , onDragStart ∷ f EventHandler
368+ , onDrop ∷ f EventHandler
369+ , onFocus ∷ f EventHandler
370+ , onGotPointerCapture ∷ f EventHandler
371+ , onInvalid ∷ f EventHandler
372+ , onKeyDown ∷ f EventHandler
373+ , onKeyPress ∷ f EventHandler
374+ , onKeyUp ∷ f EventHandler
375+ , onLostPointerCapture ∷ f EventHandler
376+ , onMouseDown ∷ f EventHandler
377+ , onMouseEnter ∷ f EventHandler
378+ , onMouseLeave ∷ f EventHandler
379+ , onMouseMove ∷ f EventHandler
380+ , onMouseOut ∷ f EventHandler
381+ , onMouseOver ∷ f EventHandler
382+ , onMouseUp ∷ f EventHandler
383+ , onPaste ∷ f EventHandler
384+ , onPointerCancel ∷ f EventHandler
385+ , onPointerDown ∷ f EventHandler
386+ , onPointerEnter ∷ f EventHandler
387+ , onPointerLeave ∷ f EventHandler
388+ , onPointerMove ∷ f EventHandler
389+ , onPointerOut ∷ f EventHandler
390+ , onPointerOver ∷ f EventHandler
391+ , onPointerUp ∷ f EventHandler
392+ , onSelect ∷ f EventHandler
393+ , onSubmit ∷ f EventHandler
394+ , onTouchCancel ∷ f EventHandler
395+ , onTouchEnd ∷ f EventHandler
396+ , onTouchMove ∷ f EventHandler
397+ , onTouchStart ∷ f EventHandler
398+ , onTransitionEnd ∷ f EventHandler
399+ , onWheel ∷ f EventHandler
400+ , prefix ∷ f String
401+ , property ∷ f String
402+ , radioGroup ∷ f String
403+ , readOnly ∷ f Boolean
404+ , ref ∷ f (Ref (Nullable Node))
405+ , resource ∷ f String
406+ , role ∷ f String
407+ , rowSpan ∷ f Int
408+ , scoped ∷ f Boolean
409+ , seamless ∷ f Boolean
410+ , security ∷ f String
411+ , spellCheck ∷ f Boolean
412+ , srcDoc ∷ f JSX
413+ , srcLang ∷ f String
414+ , srcSet ∷ f String
415+ , style ∷ f CSS
416+ , suppressContentEditableWarning ∷ f Boolean
417+ , tabIndex ∷ f Int
418+ , title ∷ f String
419+ , typeof ∷ f String
420+ , unselectable ∷ f Boolean
421+ , useMap ∷ f String
422+ , vocab ∷ f String
423+ , wmode ∷ f String
424+ | more
425+ )
426+
427+type InputReadableProps = InputReadablePropsF OptionalProp ()
428+
429+type InputWritableProps = InputWritablePropsF Id ()
430+
431+type InputWritablePropsF f more = InputReadablePropsF f
432+ ( ref ∷ f (Ref (Nullable Node))
433+ | more
434+ )
435+
436+type InputReadablePropsF f more =
437+ ( _aria ∷ f (Object String)
438+ , _data ∷ f (Object String)
439+ , about ∷ f String
440+ , accept ∷ f String
441+ , acceptCharset ∷ f String
442+ , accessKey ∷ f String
443+ , allowFullScreen ∷ f Boolean
444+ , alt ∷ f String
445+ , autoCapitalize ∷ f String
446+ , autoComplete ∷ f String
447+ , autoCorrect ∷ f String
448+ , autoFocus ∷ f Boolean
449+ , autoPlay ∷ f Boolean
450+ , autoSave ∷ f String
451+ , capture ∷ f Boolean
452+ , cellPadding ∷ f String
453+ , cellSpacing ∷ f String
454+ , charSet ∷ f String
455+ , checked ∷ f Boolean
456+ , classID ∷ f String
457+ , colSpan ∷ f Int
458+ , contentEditable ∷ f Boolean
459+ , contextMenu ∷ f String
460+ , crossOrigin ∷ f String
461+ , dangerouslySetInnerHTML ∷ f { __html ∷ f String }
462+ , datatype ∷ f String
463+ , dateTime ∷ f String
464+ , defaultChecked ∷ f String
465+ , defaultValue ∷ f String
466+ , dir ∷ f String
467+ , disabled ∷ f Boolean
468+ , draggable ∷ f Boolean
469+ , encType ∷ f String
470+ , form ∷ f String
471+ , formAction ∷ f String
472+ , formEncType ∷ f String
473+ , formMethod ∷ f String
474+ , formNoValidate ∷ f Boolean
475+ , formTarget ∷ f String
476+ , frameBorder ∷ f String
477+ , height ∷ f String
478+ , hidden ∷ f Boolean
479+ , hrefLang ∷ f String
480+ , htmlFor ∷ f String
481+ , httpEquiv ∷ f String
482+ , icon ∷ f String
483+ , id ∷ f String
484+ , inlist ∷ f String
485+ , inputMode ∷ f String
486+ , is ∷ f String
487+ , itemID ∷ f String
488+ , itemProp ∷ f String
489+ , itemRef ∷ f String
490+ , itemScope ∷ f Boolean
491+ , itemType ∷ f String
492+ , keyParams ∷ f String
493+ , keyType ∷ f String
494+ , lang ∷ f String
495+ , list ∷ f String
496+ , marginHeight ∷ f String
497+ , marginWidth ∷ f String
498+ , maxLength ∷ f Int
499+ , mediaGroup ∷ f String
500+ , minLength ∷ f Int
501+ , multiple ∷ f Boolean
502+ , name ∷ f String
503+ , noValidate ∷ f Boolean
504+ , onAnimationEnd ∷ f EventHandler
505+ , onAnimationIteration ∷ f EventHandler
506+ , onAnimationStart ∷ f EventHandler
507+ , onBlur ∷ f EventHandler
508+ , onChange ∷ f EventHandler
509+ , onClick ∷ f EventHandler
510+ , onCompositionEnd ∷ f EventHandler
511+ , onCompositionStart ∷ f EventHandler
512+ , onCompositionUpdate ∷ f EventHandler
513+ , onContextMenu ∷ f EventHandler
514+ , onCopy ∷ f EventHandler
515+ , onCut ∷ f EventHandler
516+ , onDoubleClick ∷ f EventHandler
517+ , onDrag ∷ f EventHandler
518+ , onDragEnd ∷ f EventHandler
519+ , onDragEnter ∷ f EventHandler
520+ , onDragExit ∷ f EventHandler
521+ , onDragLeave ∷ f EventHandler
522+ , onDragOver ∷ f EventHandler
523+ , onDragStart ∷ f EventHandler
524+ , onDrop ∷ f EventHandler
525+ , onFocus ∷ f EventHandler
526+ , onGotPointerCapture ∷ f EventHandler
527+ , onInvalid ∷ f EventHandler
528+ , onKeyDown ∷ f EventHandler
529+ , onKeyPress ∷ f EventHandler
530+ , onKeyUp ∷ f EventHandler
531+ , onLostPointerCapture ∷ f EventHandler
532+ , onMouseDown ∷ f EventHandler
533+ , onMouseEnter ∷ f EventHandler
534+ , onMouseLeave ∷ f EventHandler
535+ , onMouseMove ∷ f EventHandler
536+ , onMouseOut ∷ f EventHandler
537+ , onMouseOver ∷ f EventHandler
538+ , onMouseUp ∷ f EventHandler
539+ , onPaste ∷ f EventHandler
540+ , onPointerCancel ∷ f EventHandler
541+ , onPointerDown ∷ f EventHandler
542+ , onPointerEnter ∷ f EventHandler
543+ , onPointerLeave ∷ f EventHandler
544+ , onPointerMove ∷ f EventHandler
545+ , onPointerOut ∷ f EventHandler
546+ , onPointerOver ∷ f EventHandler
547+ , onPointerUp ∷ f EventHandler
548+ , onSelect ∷ f EventHandler
549+ , onSubmit ∷ f EventHandler
550+ , onTouchCancel ∷ f EventHandler
551+ , onTouchEnd ∷ f EventHandler
552+ , onTouchMove ∷ f EventHandler
553+ , onTouchStart ∷ f EventHandler
554+ , onTransitionEnd ∷ f EventHandler
555+ , onWheel ∷ f EventHandler
556+ , pattern ∷ f String
557+ , placeholder ∷ f String
558+ , prefix ∷ f String
559+ , property ∷ f String
560+ , radioGroup ∷ f String
561+ -- , ref ∷ f (Ref (Nullable Node))
562+ , readOnly ∷ f Boolean
563+ , required ∷ f Boolean
564+ , resource ∷ f String
565+ , results ∷ f String
566+ , role ∷ f String
567+ , rowSpan ∷ f Int
568+ , scoped ∷ f Boolean
569+ , seamless ∷ f Boolean
570+ , security ∷ f String
571+ , size ∷ f Int
572+ , spellCheck ∷ f Boolean
573+ , src ∷ f String
574+ , srcDoc ∷ f JSX
575+ , srcLang ∷ f String
576+ , srcSet ∷ f String
577+ , step ∷ f String
578+ , style ∷ f CSS
579+ , suppressContentEditableWarning ∷ f Boolean
580+ , tabIndex ∷ f Int
581+ , title ∷ f String
582+ , type ∷ f String
583+ , typeof ∷ f String
584+ , unselectable ∷ f Boolean
585+ , useMap ∷ f String
586+ , value ∷ f String
587+ , vocab ∷ f String
588+ , width ∷ f String
589+ , wmode ∷ f String
590+ , min ∷ f (String)
591+ , max ∷ f (String)
592+ | more
593+ )
594+
595+type ButtonReadableProps = ButtonReadablePropsF OptionalProp ()
596+
597+type ButtonWritableProps = ButtonWritablePropsF Id ()
598598
599599type ButtonWritablePropsF :: forall k. (Type -> k) -> Row k -> Row k
600−type ButtonWritablePropsF f more
601− = ButtonReadablePropsF f
602− ( ref ∷ f (Ref (Nullable Node))
603− | more
604− )
600+type ButtonWritablePropsF f more = ButtonReadablePropsF f
601+ ( ref ∷ f (Ref (Nullable Node))
602+ | more
603+ )
605604
606605type ButtonWritablePropsNoChildrenF :: forall k. (Type -> k) -> Row k -> Row k
607−type ButtonWritablePropsNoChildrenF f more
608− = ButtonReadablePropsNoChildrenF f
609− ( ref ∷ f (Ref (Nullable Node))
610− | more
611− )
606+type ButtonWritablePropsNoChildrenF f more = ButtonReadablePropsNoChildrenF f
607+ ( ref ∷ f (Ref (Nullable Node))
608+ | more
609+ )
612610
613611type ButtonReadablePropsF :: forall k. (Type -> k) -> Row k -> Row k
614−type ButtonReadablePropsF f more
615− = ButtonReadablePropsNoChildrenF f ( children ∷ f (Array JSX) | more)
616−
612+type ButtonReadablePropsF f more = ButtonReadablePropsNoChildrenF f (children ∷ f (Array JSX) | more)
613+
617614type ButtonReadablePropsNoChildrenF :: forall k. (Type -> k) -> Row k -> Row k
618−type ButtonReadablePropsNoChildrenF f more
619− = ( _aria ∷ f (Object String)
620− , _data ∷ f (Object String)
621− , about ∷ f String
622− , acceptCharset ∷ f String
623− , accessKey ∷ f String
624− , allowFullScreen ∷ f Boolean
625− , allowTransparency ∷ f Boolean
626− , autoFocus ∷ f Boolean
627− , autoPlay ∷ f Boolean
628− , capture ∷ f Boolean
629− , cellPadding ∷ f String
630− , cellSpacing ∷ f String
631− , charSet ∷ f String
632− , classID ∷ f String
633− , className ∷ f String
634− , colSpan ∷ f Int
635− , contentEditable ∷ f Boolean
636− , contextMenu ∷ f String
637− , crossOrigin ∷ f String
638− , dangerouslySetInnerHTML ∷ f { __html ∷ String }
639− , datatype ∷ f String
640− , dateTime ∷ f String
641− , dir ∷ f String
642− , disabled ∷ f Boolean
643− , draggable ∷ f Boolean
644− , encType ∷ f String
645− , form ∷ f String
646− , formAction ∷ f String
647− , formEncType ∷ f String
648− , formMethod ∷ f String
649− , formNoValidate ∷ f Boolean
650− , formTarget ∷ f String
651− , frameBorder ∷ f String
652− , hidden ∷ f Boolean
653− , hrefLang ∷ f String
654− , htmlFor ∷ f String
655− , httpEquiv ∷ f String
656− , icon ∷ f String
657− , id ∷ f String
658− , inlist ∷ f String
659− , inputMode ∷ f String
660− , is ∷ f String
661− , itemID ∷ f String
662− , itemProp ∷ f String
663− , itemRef ∷ f String
664− , itemScope ∷ f Boolean
665− , itemType ∷ f String
666− , key ∷ f String
667− , keyParams ∷ f String
668− , keyType ∷ f String
669− , lang ∷ f String
670− , marginHeight ∷ f String
671− , marginWidth ∷ f String
672− , maxLength ∷ f Int
673− , mediaGroup ∷ f String
674− , minLength ∷ f Int
675− , name ∷ f String
676− , noValidate ∷ f Boolean
677− , onAnimationEnd ∷ f EventHandler
678− , onAnimationIteration ∷ f EventHandler
679− , onAnimationStart ∷ f EventHandler
680− , onBlur ∷ f EventHandler
681− , onClick ∷ f EventHandler
682− , onCompositionEnd ∷ f EventHandler
683− , onCompositionStart ∷ f EventHandler
684− , onCompositionUpdate ∷ f EventHandler
685− , onContextMenu ∷ f EventHandler
686− , onCopy ∷ f EventHandler
687− , onCut ∷ f EventHandler
688− , onDoubleClick ∷ f EventHandler
689− , onDrag ∷ f EventHandler
690− , onDragEnd ∷ f EventHandler
691− , onDragEnter ∷ f EventHandler
692− , onDragExit ∷ f EventHandler
693− , onDragLeave ∷ f EventHandler
694− , onDragOver ∷ f EventHandler
695− , onDragStart ∷ f EventHandler
696− , onDrop ∷ f EventHandler
697− , onFocus ∷ f EventHandler
698− , onGotPointerCapture ∷ f EventHandler
699− , onInvalid ∷ f EventHandler
700− , onKeyDown ∷ f EventHandler
701− , onKeyPress ∷ f EventHandler
702− , onKeyUp ∷ f EventHandler
703− , onLostPointerCapture ∷ f EventHandler
704− , onMouseDown ∷ f EventHandler
705− , onMouseEnter ∷ f EventHandler
706− , onMouseLeave ∷ f EventHandler
707− , onMouseMove ∷ f EventHandler
708− , onMouseOut ∷ f EventHandler
709− , onMouseOver ∷ f EventHandler
710− , onMouseUp ∷ f EventHandler
711− , onPaste ∷ f EventHandler
712− , onPointerCancel ∷ f EventHandler
713− , onPointerDown ∷ f EventHandler
714− , onPointerEnter ∷ f EventHandler
715− , onPointerLeave ∷ f EventHandler
716− , onPointerMove ∷ f EventHandler
717− , onPointerOut ∷ f EventHandler
718− , onPointerOver ∷ f EventHandler
719− , onPointerUp ∷ f EventHandler
720− , onSelect ∷ f EventHandler
721− , onSubmit ∷ f EventHandler
722− , onTouchCancel ∷ f EventHandler
723− , onTouchEnd ∷ f EventHandler
724− , onTouchMove ∷ f EventHandler
725− , onTouchStart ∷ f EventHandler
726− , onTransitionEnd ∷ f EventHandler
727− , onWheel ∷ f EventHandler
728− , prefix ∷ f String
729− , property ∷ f String
730− , radioGroup ∷ f String
731− , readOnly ∷ f Boolean
732− , resource ∷ f String
733− , role ∷ f String
734− , rowSpan ∷ f Int
735− , scoped ∷ f Boolean
736− , seamless ∷ f Boolean
737− , security ∷ f String
738− , spellCheck ∷ f Boolean
739− , srcDoc ∷ f JSX
740− , srcLang ∷ f String
741− , srcSet ∷ f String
742− , style ∷ f CSS
743− , suppressContentEditableWarning ∷ f Boolean
744− , tabIndex ∷ f Int
745− , title ∷ f String
746− , type ∷ f String
747− , typeof ∷ f String
748− , unselectable ∷ f Boolean
749− , useMap ∷ f String
750− , value ∷ f String
751− , vocab ∷ f String
752− , wmode ∷ f String
753− | more
754− )
615+type ButtonReadablePropsNoChildrenF f more =
616+ ( _aria ∷ f (Object String)
617+ , _data ∷ f (Object String)
618+ , about ∷ f String
619+ , acceptCharset ∷ f String
620+ , accessKey ∷ f String
621+ , allowFullScreen ∷ f Boolean
622+ , allowTransparency ∷ f Boolean
623+ , autoFocus ∷ f Boolean
624+ , autoPlay ∷ f Boolean
625+ , capture ∷ f Boolean
626+ , cellPadding ∷ f String
627+ , cellSpacing ∷ f String
628+ , charSet ∷ f String
629+ , classID ∷ f String
630+ , className ∷ f String
631+ , colSpan ∷ f Int
632+ , contentEditable ∷ f Boolean
633+ , contextMenu ∷ f String
634+ , crossOrigin ∷ f String
635+ , dangerouslySetInnerHTML ∷ f { __html ∷ String }
636+ , datatype ∷ f String
637+ , dateTime ∷ f String
638+ , dir ∷ f String
639+ , disabled ∷ f Boolean
640+ , draggable ∷ f Boolean
641+ , encType ∷ f String
642+ , form ∷ f String
643+ , formAction ∷ f String
644+ , formEncType ∷ f String
645+ , formMethod ∷ f String
646+ , formNoValidate ∷ f Boolean
647+ , formTarget ∷ f String
648+ , frameBorder ∷ f String
649+ , hidden ∷ f Boolean
650+ , hrefLang ∷ f String
651+ , htmlFor ∷ f String
652+ , httpEquiv ∷ f String
653+ , icon ∷ f String
654+ , id ∷ f String
655+ , inlist ∷ f String
656+ , inputMode ∷ f String
657+ , is ∷ f String
658+ , itemID ∷ f String
659+ , itemProp ∷ f String
660+ , itemRef ∷ f String
661+ , itemScope ∷ f Boolean
662+ , itemType ∷ f String
663+ , key ∷ f String
664+ , keyParams ∷ f String
665+ , keyType ∷ f String
666+ , lang ∷ f String
667+ , marginHeight ∷ f String
668+ , marginWidth ∷ f String
669+ , maxLength ∷ f Int
670+ , mediaGroup ∷ f String
671+ , minLength ∷ f Int
672+ , name ∷ f String
673+ , noValidate ∷ f Boolean
674+ , onAnimationEnd ∷ f EventHandler
675+ , onAnimationIteration ∷ f EventHandler
676+ , onAnimationStart ∷ f EventHandler
677+ , onBlur ∷ f EventHandler
678+ , onClick ∷ f EventHandler
679+ , onCompositionEnd ∷ f EventHandler
680+ , onCompositionStart ∷ f EventHandler
681+ , onCompositionUpdate ∷ f EventHandler
682+ , onContextMenu ∷ f EventHandler
683+ , onCopy ∷ f EventHandler
684+ , onCut ∷ f EventHandler
685+ , onDoubleClick ∷ f EventHandler
686+ , onDrag ∷ f EventHandler
687+ , onDragEnd ∷ f EventHandler
688+ , onDragEnter ∷ f EventHandler
689+ , onDragExit ∷ f EventHandler
690+ , onDragLeave ∷ f EventHandler
691+ , onDragOver ∷ f EventHandler
692+ , onDragStart ∷ f EventHandler
693+ , onDrop ∷ f EventHandler
694+ , onFocus ∷ f EventHandler
695+ , onGotPointerCapture ∷ f EventHandler
696+ , onInvalid ∷ f EventHandler
697+ , onKeyDown ∷ f EventHandler
698+ , onKeyPress ∷ f EventHandler
699+ , onKeyUp ∷ f EventHandler
700+ , onLostPointerCapture ∷ f EventHandler
701+ , onMouseDown ∷ f EventHandler
702+ , onMouseEnter ∷ f EventHandler
703+ , onMouseLeave ∷ f EventHandler
704+ , onMouseMove ∷ f EventHandler
705+ , onMouseOut ∷ f EventHandler
706+ , onMouseOver ∷ f EventHandler
707+ , onMouseUp ∷ f EventHandler
708+ , onPaste ∷ f EventHandler
709+ , onPointerCancel ∷ f EventHandler
710+ , onPointerDown ∷ f EventHandler
711+ , onPointerEnter ∷ f EventHandler
712+ , onPointerLeave ∷ f EventHandler
713+ , onPointerMove ∷ f EventHandler
714+ , onPointerOut ∷ f EventHandler
715+ , onPointerOver ∷ f EventHandler
716+ , onPointerUp ∷ f EventHandler
717+ , onSelect ∷ f EventHandler
718+ , onSubmit ∷ f EventHandler
719+ , onTouchCancel ∷ f EventHandler
720+ , onTouchEnd ∷ f EventHandler
721+ , onTouchMove ∷ f EventHandler
722+ , onTouchStart ∷ f EventHandler
723+ , onTransitionEnd ∷ f EventHandler
724+ , onWheel ∷ f EventHandler
725+ , prefix ∷ f String
726+ , property ∷ f String
727+ , radioGroup ∷ f String
728+ , readOnly ∷ f Boolean
729+ , resource ∷ f String
730+ , role ∷ f String
731+ , rowSpan ∷ f Int
732+ , scoped ∷ f Boolean
733+ , seamless ∷ f Boolean
734+ , security ∷ f String
735+ , spellCheck ∷ f Boolean
736+ , srcDoc ∷ f JSX
737+ , srcLang ∷ f String
738+ , srcSet ∷ f String
739+ , style ∷ f CSS
740+ , suppressContentEditableWarning ∷ f Boolean
741+ , tabIndex ∷ f Int
742+ , title ∷ f String
743+ , type ∷ f String
744+ , typeof ∷ f String
745+ , unselectable ∷ f Boolean
746+ , useMap ∷ f String
747+ , value ∷ f String
748+ , vocab ∷ f String
749+ , wmode ∷ f String
750+ | more
751+ )
src/Yoga/Block/Internal/OptionalProp.purs+12−10
@@ -1,16 +1,18 @@
11module Yoga.Block.Internal.OptionalProp where
22
33import Prelude
4+
45import Control.Alt (class Alt, (<|>))
56import Data.Foldable (class Foldable, foldMap, foldl, foldr, for_)
67import Data.Maybe (Maybe(..), maybe)
78import Data.Newtype (class Newtype)
8−import Data.Symbol (class IsSymbol, SProxy, reflectSymbol)
9+import Data.Symbol (class IsSymbol, reflectSymbol)
910import Effect.Uncurried (mkEffectFn1, runEffectFn1)
1011import Prim.Row (class Cons)
1112import React.Basic.Events (EventHandler)
1213import Record (set)
1314import Record.Unsafe (unsafeDelete)
15+import Type.Proxy (Proxy(..))
1416import Unsafe.Coerce (unsafeCoerce)
1517import Untagged.Castable (class Castable, cast)
1618import Untagged.Union (UndefinedOr, defined, fromUndefinedOr, maybeToUor, uorToMaybe)
@@ -20,14 +22,14 @@ type Id a = a
2022
2123newtype OptionalProp a = OptionalProp (UndefinedOr a)
2224
23−setOrDelete ∷
24− ∀ r a rNoA key.
25− IsSymbol key =>
26− Cons key a rNoA r =>
27− SProxy key ->
28− OptionalProp a ->
29− { | r } ->
30− { | r }
25+setOrDelete
26+ ∷ ∀ r a rNoA key
27+ . IsSymbol key
28+ => Cons key a rNoA r
29+ => Proxy key
30+ -> OptionalProp a
31+ -> { | r }
32+ -> { | r }
3133setOrDelete key v = case opToMaybe v of
3234 Nothing -> unsafeDelete (reflectSymbol key)
3335 Just v' -> set key v'
@@ -41,8 +43,8 @@ asMaybe = asOptional >>> opToMaybe
4143composeHandler ∷ EventHandler -> OptionalProp EventHandler -> EventHandler
4244composeHandler handler propsHandler =
4345 mkEffectFn1 \a -> do
44− for_ (propsHandler # opToMaybe) $ flip runEffectFn1 a
4546 for_ (handler # asMaybe) $ flip runEffectFn1 a
47+ for_ (propsHandler # opToMaybe) $ flip runEffectFn1 a
4648
4749unsafeUnOptional ∷ ∀ a. OptionalProp a -> a
4850unsafeUnOptional = unsafeCoerce
src/Yoga/Block/Molecule/Sheet/View.purs+67−63
@@ -2,11 +2,11 @@ module Yoga.Block.Molecule.Sheet.View (component, Props) where
22
33import Yoga.Prelude.View
44import Data.Int as Int
5+import Data.Number (pow)
56import Data.Nullable as Nullable
67import Effect.Class.Console (log)
78import Effect.Unsafe (unsafePerformEffect)
89import Framer.Motion as Motion
9−import Math as Math
1010import MotionValue (useMotionValue)
1111import MotionValue as MotionValue
1212import React.Basic.DOM (createPortal, css)
@@ -41,7 +41,8 @@ component =
4141 toRender ∷ JSX
4242 toRender =
4343 R.div' </ {}
44− /> [ Motion.animatePresence </ {} /> [ guard isOpen $ element clickaway { theRef: clickAwayRef, onDismiss } ]
44+ />
45+ [ Motion.animatePresence </ {} /> [ guard isOpen $ element clickaway { theRef: clickAwayRef, onDismiss } ]
4546 , element window { onDismiss, content, isOpen }
4647 ]
4748 pure (createPortal toRender target)
@@ -51,7 +52,8 @@ clickaway =
5152 unsafePerformEffect
5253 $ reactComponent "Sheet Clickaway" \{ theRef, onDismiss } -> React.do
5354 pure $ Emotion.elementKeyed Motion.div
54− $ { key: "ry-modal-clickaway"
55+ $
56+ { key: "ry-modal-clickaway"
5557 , onClick: handler_ onDismiss
5658 , className: "ry-modal-clickaway"
5759 , css: Style.clickaway
@@ -76,6 +78,7 @@ window =
7678 let
7779 getWindowHeight = do
7880 HTML.window >>= innerHeight <#> Int.toNumber
81+
7982 getMaxHeight ∷ Effect Number
8083 getMaxHeight = do
8184 wh <- getWindowHeight
@@ -88,82 +91,83 @@ window =
8891 pure
8992 $ Motion.animatePresence
9093 </ {}
91− /> [ guard isOpen $ Motion.div
92− </* { className: "ry-sheet-background"
94+ />
95+ [ guard isOpen $ Motion.div
96+ </*
97+ { className: "ry-sheet-background"
9398 , css: Style.sheet
9499 , layout: Motion.layout true
95100 , style: css { top }
96101 , ref
97102 , initial: Motion.initial $ css { y: "100%" }
98103 , animate:
99− Motion.animate
100− $ css
101− { y: "0%"
102− , transition:
103− { type: "spring"
104− , stiffness: 1200.0
105− , damping: 90.0
104+ Motion.animate
105+ $ css
106+ { y: "0%"
107+ , transition:
108+ { type: "spring"
109+ , stiffness: 1200.0
110+ , damping: 90.0
111+ }
106112 }
107− }
108113 , exit: Motion.exit $ css { top: "100%" }
109114 , onPanStart:
110− Motion.onPanStart \_ _ -> do
111− maybeRunningAnimation <- React.readRef animationRef
112− for_ maybeRunningAnimation MotionValue.stopAnimation
113− React.writeRef animationRef Nothing
115+ Motion.onPanStart \_ _ -> do
116+ maybeRunningAnimation <- React.readRef animationRef
117+ for_ maybeRunningAnimation MotionValue.stopAnimation
118+ React.writeRef animationRef Nothing
114119 , onPan:
115− Motion.onPan \_ pi -> do
116− oldY <- MotionValue.get top
117− maxHeight <- getMaxHeight
118− React.writeRef velocityRef pi.velocity.y
119− let
120− newNaiveValue = pi.delta.y + oldY
121− newY =
122− if (newNaiveValue < maxHeight) && (pi.delta.y < zero) then
123− negate (Math.pow (negate pi.delta.y) 0.33) + oldY
124− else
125− if (newNaiveValue < maxHeight) && (pi.delta.y > zero) then
126− (Math.pow (pi.delta.y) 0.33) + oldY
120+ Motion.onPan \_ pi -> do
121+ oldY <- MotionValue.get top
122+ maxHeight <- getMaxHeight
123+ React.writeRef velocityRef pi.velocity.y
124+ let
125+ newNaiveValue = pi.delta.y + oldY
126+ newY =
127+ if (newNaiveValue < maxHeight) && (pi.delta.y < zero) then
128+ negate (pow (negate pi.delta.y) 0.33) + oldY
129+ else if (newNaiveValue < maxHeight) && (pi.delta.y > zero) then
130+ (pow (pi.delta.y) 0.33) + oldY
127131 else
128132 newNaiveValue
129− MotionValue.set newY top
133+ MotionValue.set newY top
130134 , onPanEnd:
131− Motion.onPanEnd \_ pi -> do
132− velocity <- React.readRef velocityRef
133− yValue <- MotionValue.get top
134− maxHeight <- getMaxHeight
135− windowHeight <- getWindowHeight
136− let percentPosition = ((yValue - maxHeight) / (windowHeight - maxHeight))
137− let
138− target =
139− if percentPosition > 0.7 then
140− windowHeight
141− else
142− if percentPosition < 0.2 then
135+ Motion.onPanEnd \_ pi -> do
136+ velocity <- React.readRef velocityRef
137+ yValue <- MotionValue.get top
138+ maxHeight <- getMaxHeight
139+ windowHeight <- getWindowHeight
140+ let percentPosition = ((yValue - maxHeight) / (windowHeight - maxHeight))
141+ let
142+ target =
143+ if percentPosition > 0.7 then
144+ windowHeight
145+ else if percentPosition < 0.2 then
143146 maxHeight
147+ else if velocity > 70.0 then
148+ windowHeight
144149 else
145− if velocity > 70.0 then
146− windowHeight
147− else
148− maxHeight
149− animation <-
150− MotionValue.animate target
151− { type: "spring"
152− , velocity: pi.velocity.y
153− , stiffness: 1200.0
154− , damping: 90.0
155− , onComplete:
156− do
157− log "complete"
158− React.writeRef animationRef Nothing
159− when (target == windowHeight) do
160− onDismiss
161− }
162− top
163− React.writeRef animationRef (Just animation)
150+ maxHeight
151+ animation <-
152+ MotionValue.animate target
153+ { type: "spring"
154+ , velocity: pi.velocity.y
155+ , stiffness: 1200.0
156+ , damping: 90.0
157+ , onComplete:
158+ do
159+ log "complete"
160+ React.writeRef animationRef Nothing
161+ when (target == windowHeight) do
162+ onDismiss
163+ }
164+ top
165+ React.writeRef animationRef (Just animation)
164166 }
165− /> [ R.div'
166− </* { ref: contentRef
167+ />
168+ [ R.div'
169+ </*
170+ { ref: contentRef
167171 , css: Style.sheetContent
168172 , className: "ry-sheet-content"
169173 }
src/Yoga/Block/Organism/Form.purs+427−426
@@ -35,7 +35,6 @@ import Data.Newtype (un)
3535import Data.String as String
3636import Data.String.NonEmpty (NonEmptyString)
3737import Data.Traversable (traverse)
38−import Effect.Uncurried (mkEffectFn1)
3938import Effect.Unsafe (unsafePerformEffect)
4039import Foreign.Object (Object)
4140import Foreign.Object as Object
@@ -45,7 +44,6 @@ import React.Basic.DOM as R
4544import React.Basic.Emotion as E
4645import React.Basic.Hooks (reactComponent)
4746import React.Basic.Hooks as Hooks
48−import React.Basic.Popper (nullRef)
4947import React.DndKit as Dnd
5048import Record (disjointUnion)
5149import Record.Builder as RB
@@ -67,14 +65,14 @@ import Yoga.Block.Organism.Form.Validation (ModifyValidated(..), Validated(..),
6765-- |
6866-- | _Note_: this function should be fully applied, to avoid remounting
6967-- | the component on each render.
70−build ∷
71− ∀ props unvalidated result.
72− FormBuilder { readOnly ∷ Boolean | props } unvalidated result ->
73− ReactComponent
74− { value ∷ unvalidated
75− , onChange ∷ (unvalidated -> unvalidated) -> Effect Unit
76− , formProps ∷ { readOnly ∷ Boolean | props }
77− }
68+build
69+ ∷ ∀ props unvalidated result
70+ . FormBuilder { readOnly ∷ Boolean | props } unvalidated result
71+ -> ReactComponent
72+ { value ∷ unvalidated
73+ , onChange ∷ (unvalidated -> unvalidated) -> Effect Unit
74+ , formProps ∷ { readOnly ∷ Boolean | props }
75+ }
7876build = build' defaultRenderForm
7977
8078-- | Create a React component for a form from a `FormBuilder'` and a custom
@@ -82,54 +80,56 @@ build = build' defaultRenderForm
8280-- |
8381-- | _Note_: this function should be fully applied, to avoid remounting
8482-- | the component on each render.
85−build' ∷
86− ∀ ui renderProps formProps unvalidated result.
87− Lacks "children" renderProps =>
88− Lacks "key" renderProps =>
89− Lacks "ref" renderProps =>
90− ({ | renderProps } -> formProps -> ui -> JSX) ->
91− FormBuilder' ui formProps unvalidated result ->
92− ReactComponent
93− { value ∷ unvalidated
94− , onChange ∷ (unvalidated -> unvalidated) -> Effect Unit
95− , formProps ∷ formProps
96− | renderProps
97− }
83+build'
84+ ∷ ∀ ui renderProps formProps unvalidated result
85+ . Lacks "children" renderProps
86+ => Lacks "key" renderProps
87+ => Lacks "ref" renderProps
88+ => ({ | renderProps } -> formProps -> ui -> JSX)
89+ -> FormBuilder' ui formProps unvalidated result
90+ -> ReactComponent
91+ { value ∷ unvalidated
92+ , onChange ∷ (unvalidated -> unvalidated) -> Effect Unit
93+ , formProps ∷ formProps
94+ | renderProps
95+ }
9896build' render editor =
9997 unsafePerformEffect
10098 $ reactComponent "Form" \props@{ value, onChange, formProps } -> React.do
10199 let { edit } = un FormBuilder editor formProps value
102100 pure $ render (contractRenderProps props) formProps (edit onChange)
103101 where
104− contractRenderProps ∷
105− { value ∷ unvalidated
106− , onChange ∷ (unvalidated -> unvalidated) -> Effect Unit
107− , formProps ∷ formProps
108− | renderProps
109− } ->
110− { | renderProps }
102+ contractRenderProps
103+ ∷ { value ∷ unvalidated
104+ , onChange ∷ (unvalidated -> unvalidated) -> Effect Unit
105+ , formProps ∷ formProps
106+ | renderProps
107+ }
108+ -> { | renderProps }
111109 contractRenderProps = unsafeCoerce
112110
113111-- | The default Lumi implementation for rendering a forest of JSX
114112-- | form fields.
115−defaultRenderForm ∷
116− ∀ props.
117− {} ->
118− { readOnly ∷ Boolean
119− | props
120− } ->
121− Forest ->
122− JSX
113+defaultRenderForm
114+ ∷ ∀ props
115+ . {}
116+ -> { readOnly ∷ Boolean
117+ | props
118+ }
119+ -> Forest
120+ -> JSX
123121defaultRenderForm _ { readOnly } forest =
124122 R.div'
125− </ { className:
126− String.joinWith " "
127− $ fold
128− [ [ "ry-form" ]
129− , guard readOnly [ "readOnly" ]
130− ]
123+ </
124+ { className:
125+ String.joinWith " "
126+ $ fold
127+ [ [ "ry-form" ]
128+ , guard readOnly [ "readOnly" ]
129+ ]
131130 }
132− /> [ surround fieldDivider
131+ />
132+ [ surround fieldDivider
133133 $ defaultRenderForest
134134 $ Array.mapMaybe pruneTree
135135 $ forest
@@ -137,17 +137,18 @@ defaultRenderForm _ { readOnly } forest =
137137 where
138138 fieldDivider =
139139 R.div'
140− </*> { className: "ry field-divider"
140+ </*>
141+ { className: "ry field-divider"
141142 , css:
142− E.css
143− { height: E.str $ "var(--s-2)"
144− , width: E.str "100%"
145− }
143+ E.css
144+ { height: E.str $ "var(--s-2)"
145+ , width: E.str "100%"
146+ }
146147 }
147148
148−defaultRenderForest ∷
149− Forest ->
150− Array JSX
149+defaultRenderForest
150+ ∷ Forest
151+ -> Array JSX
151152defaultRenderForest =
152153 map case _ of
153154 Child { key, child } -> maybe identity keyed key $ child
@@ -162,55 +163,59 @@ defaultRenderForest =
162163 maybe identity keyed key
163164 $ Block.box
164165 { css:
165− E.css
166− { border: E.str $ "1px solid " <> colour.inputBorder
167− , background: E.str colour.backgroundLayer1
168− , borderRadius: E.var "--s-1"
169− , marginTop: E.str "var(--s0)"
170− , "--label-bg": E.str colour.background
171− , "--label-fg": E.str colour.text
172− , "&:focus-within":
173− nest
174− { "--label-bg": labelSmallFocusBackground
175− , "--label-fg": E.str colour.highlightText
176− }
177− }
166+ E.css
167+ { border: E.str $ "1px solid " <> colour.inputBorder
168+ , background: E.str colour.backgroundLayer1
169+ , borderRadius: E.var "--s-1"
170+ , marginTop: E.str "var(--s0)"
171+ , "--label-bg": E.str colour.background
172+ , "--label-fg": E.str colour.text
173+ , "&:focus-within":
174+ nest
175+ { "--label-bg": labelSmallFocusBackground
176+ , "--label-fg": E.str colour.highlightText
177+ }
178+ }
178179 , padding: E.str "0"
179180 } --space: E.var "--s-2", css: E.css { marginTop: E.var "--s-1" } }
180181 ( [ R.div'
181− </* { className: "ry-form-label"
182+ </*
183+ { className: "ry-form-label"
182184 , css:
183− labelSmall colour.background colour.text
184− <> E.css
185+ labelSmall colour.background colour.text
186+ <> E.css
185187 { position: E.absolute
186188 , display: E.inlineBlock
187189 , "& > span":
188− nest
189− { background: E.var "--label-bg"
190− , color: E.var "--label-fg"
191− }
190+ nest
191+ { background: E.var "--label-bg"
192+ , color: E.var "--label-fg"
193+ }
192194 }
193195 }
194196 /> [ R.span_ [ label ] ]
195197 ]
196− <> [ Block.box
198+ <>
199+ [ Block.box
197200 { padding: E.var "--s-2"
198201 , css: E.css { marginTop: E.var "--s0" }
199202 }
200203 [ intercalate fieldDivider (defaultRenderForest children) ]
201204 ]
202− <> [ foldMap R.text validationError
205+ <>
206+ [ foldMap R.text validationError
203207 ]
204208 )
205209 where
206210 fieldDivider =
207211 R.div'
208− </*> { className: "ry field-divider"
212+ </*>
213+ { className: "ry field-divider"
209214 , css:
210− E.css
211− { height: E.str $ "var(--s-2)"
212− , width: E.str "100%"
213− }
215+ E.css
216+ { height: E.str $ "var(--s-2)"
217+ , width: E.str "100%"
218+ }
214219 }
215220
216221-- , layout: Motion.layout false
@@ -218,21 +223,21 @@ defaultRenderForest =
218223-- , animate: Motion.animate $ R.css { scale: 1 }
219224-- , exit: Motion.exit $ R.css { scale: 0 }
220225-- | Render a form with state managed automatically.
221−useForm ∷
222− ∀ props unvalidated result.
223− Mapping Validation.ModifyValidated unvalidated unvalidated =>
224− FormBuilder { readOnly ∷ Boolean | props } unvalidated result ->
225− { initialState ∷ unvalidated
226− , formProps ∷ { readOnly ∷ Boolean | props }
227− } ->
228− Hooks.Hook (Hooks.UseState unvalidated)
229− { formData ∷ unvalidated
230− , setFormData ∷ (unvalidated -> unvalidated) -> Effect Unit
231− , setModified ∷ Effect Unit
232− , reset ∷ Effect Unit
233− , validated ∷ Maybe result
234− , form ∷ JSX
235− }
226+useForm
227+ ∷ ∀ props unvalidated result
228+ . Mapping Validation.ModifyValidated unvalidated unvalidated
229+ => FormBuilder { readOnly ∷ Boolean | props } unvalidated result
230+ -> { initialState ∷ unvalidated
231+ , formProps ∷ { readOnly ∷ Boolean | props }
232+ }
233+ -> Hooks.Hook (Hooks.UseState unvalidated)
234+ { formData ∷ unvalidated
235+ , setFormData ∷ (unvalidated -> unvalidated) -> Effect Unit
236+ , setModified ∷ Effect Unit
237+ , reset ∷ Effect Unit
238+ , validated ∷ Maybe result
239+ , form ∷ JSX
240+ }
236241useForm editor props = Hooks.do
237242 let renderer = defaultRenderForm {} props.formProps
238243 f <- useForm' editor props.initialState props.formProps
@@ -240,20 +245,20 @@ useForm editor props = Hooks.do
240245
241246-- | Like `useForm`, but allows an alternative render implementation
242247-- | to be provided as an additional argument.
243−useForm' ∷
244− ∀ ui props unvalidated result.
245− Mapping Validation.ModifyValidated unvalidated unvalidated =>
246− FormBuilder' ui props unvalidated result ->
247− unvalidated ->
248− props ->
249− Hooks.Hook (Hooks.UseState unvalidated)
250− { formData ∷ unvalidated
251− , setFormData ∷ (unvalidated -> unvalidated) -> Effect Unit
252− , setModified ∷ Effect Unit
253− , reset ∷ Effect Unit
254− , validated ∷ Maybe result
255− , form ∷ ui
256− }
248+useForm'
249+ ∷ ∀ ui props unvalidated result
250+ . Mapping Validation.ModifyValidated unvalidated unvalidated
251+ => FormBuilder' ui props unvalidated result
252+ -> unvalidated
253+ -> props
254+ -> Hooks.Hook (Hooks.UseState unvalidated)
255+ { formData ∷ unvalidated
256+ , setFormData ∷ (unvalidated -> unvalidated) -> Effect Unit
257+ , setModified ∷ Effect Unit
258+ , reset ∷ Effect Unit
259+ , validated ∷ Maybe result
260+ , form ∷ ui
261+ }
257262useForm' editor initialState props = Hooks.do
258263 formData /\ setFormData <- Hooks.useState initialState
259264 let
@@ -273,11 +278,11 @@ static ∷ ∀ props value. JSX -> FormBuilder props value Unit
273278static edit = formBuilder \_ _ -> { edit: const edit, validate: pure unit }
274279
275280-- | Focus a `FormBuilder` on a smaller piece of state, using a `Lens`.
276−focus ∷
277− ∀ ui props s a result.
278− Lens' s a ->
279− FormBuilder' ui props a result ->
280− FormBuilder' ui props s result
281+focus
282+ ∷ ∀ ui props s a result
283+ . Lens' s a
284+ -> FormBuilder' ui props a result
285+ -> FormBuilder' ui props s result
281286focus l e =
282287 FormBuilder \props s ->
283288 let
@@ -289,25 +294,25 @@ focus l e =
289294
290295-- | Focus a `FormBuilder` on a possible type of state, using a `Prism`,
291296-- | ignoring validation.
292−match_ ∷
293− ∀ ui props s a.
294− Monoid ui =>
295− Prism' s a ->
296− FormBuilder' ui props a a ->
297− FormBuilder' ui props s s
297+match_
298+ ∷ ∀ ui props s a
299+ . Monoid ui
300+ => Prism' s a
301+ -> FormBuilder' ui props a a
302+ -> FormBuilder' ui props s s
298303match_ p = match p p
299304
300305-- | Focus a `FormBuilder` on a possible type of state, using a `Prism`.
301306-- |
302307-- | We need two `Prism`s in order to change the result type for
303308-- | validation purposes.
304−match ∷
305− ∀ ui props result s t a.
306− Monoid ui =>
307− Prism s s a a ->
308− Prism s t a result ->
309− FormBuilder' ui props a result ->
310− FormBuilder' ui props s t
309+match
310+ ∷ ∀ ui props result s t a
311+ . Monoid ui
312+ => Prism s s a a
313+ -> Prism s t a result
314+ -> FormBuilder' ui props a result
315+ -> FormBuilder' ui props s t
311316match p1 p2 e =
312317 FormBuilder \props s -> case matching p2 s of
313318 Left t -> { edit: mempty, validate: pure t }
@@ -320,28 +325,28 @@ match p1 p2 e =
320325 }
321326
322327-- | Change the props type.
323−mapProps ∷
324− ∀ ui p q u a.
325− (q -> p) ->
326− FormBuilder' ui p u a ->
327− FormBuilder' ui q u a
328+mapProps
329+ ∷ ∀ ui p q u a
330+ . (q -> p)
331+ -> FormBuilder' ui p u a
332+ -> FormBuilder' ui q u a
328333mapProps f form = FormBuilder (un FormBuilder form <<< f)
329334
330335-- | Change the UI type of a form.
331−mapUI_ ∷
332− ∀ ui ui' props value result.
333− (ui -> ui') ->
334− FormBuilder' ui props value result ->
335− FormBuilder' ui' props value result
336+mapUI_
337+ ∷ ∀ ui ui' props value result
338+ . (ui -> ui')
339+ -> FormBuilder' ui props value result
340+ -> FormBuilder' ui' props value result
336341mapUI_ f = mapUI \_ _ _ -> f
337342
338343-- | Change the UI type of a form based on the props, the current value and the
339344-- | validated result.
340−mapUI ∷
341− ∀ ui ui' props value result.
342− (props -> value -> Maybe result -> ui -> ui') ->
343− FormBuilder' ui props value result ->
344− FormBuilder' ui' props value result
345+mapUI
346+ ∷ ∀ ui ui' props value result
347+ . (props -> value -> Maybe result -> ui -> ui')
348+ -> FormBuilder' ui props value result
349+ -> FormBuilder' ui' props value result
345350mapUI f form =
346351 FormBuilder \props value ->
347352 let
@@ -353,105 +358,105 @@ mapUI f form =
353358
354359-- | Make the props available. This allows for changing the structure of a form
355360-- | builder based on the current props.
356−withProps ∷
357− ∀ ui props unvalidated result.
358− (props -> FormBuilder' ui props unvalidated result) ->
359− FormBuilder' ui props unvalidated result
361+withProps
362+ ∷ ∀ ui props unvalidated result
363+ . (props -> FormBuilder' ui props unvalidated result)
364+ -> FormBuilder' ui props unvalidated result
360365withProps f = FormBuilder \props value -> un FormBuilder (f props) props value
361366
362367-- | Make the value available. This allows for changing the structure of a form
363368-- | builder based on the current value.
364−withValue ∷
365− ∀ ui props unvalidated result.
366− (unvalidated -> FormBuilder' ui props unvalidated result) ->
367− FormBuilder' ui props unvalidated result
369+withValue
370+ ∷ ∀ ui props unvalidated result
371+ . (unvalidated -> FormBuilder' ui props unvalidated result)
372+ -> FormBuilder' ui props unvalidated result
368373withValue f = FormBuilder \props value -> un FormBuilder (f value) props value
369374
370375-- | Indent a `Forest` of editors by one level, providing a label.
371−indent ∷
372− ∀ props u a.
373− String ->
374− RequiredField ->
375− FormBuilder props u a ->
376− FormBuilder props u a
376+indent
377+ ∷ ∀ props u a
378+ . String
379+ -> RequiredField
380+ -> FormBuilder props u a
381+ -> FormBuilder props u a
377382indent label required editor =
378383 FormBuilder \props val ->
379384 let
380385 { edit, validate } = un FormBuilder editor props val
381386 in
382387 { edit:
383− \k ->
384− pure
385− $ Node
386− { label: R.text label
387− , key: Nothing
388− , required: required
389− , validationError: Nothing
390− , children: edit k
391− }
388+ \k ->
389+ pure
390+ $ Node
391+ { label: R.text label
392+ , key: Nothing
393+ , required
394+ , validationError: Nothing
395+ , children: edit k
396+ }
392397 , validate
393398 }
394399
395−wrap ∷
396− ∀ props u a.
397− (Array JSX -> JSX) ->
398− FormBuilder props u a ->
399− FormBuilder props u a
400+wrap
401+ ∷ ∀ props u a
402+ . (Array JSX -> JSX)
403+ -> FormBuilder props u a
404+ -> FormBuilder props u a
400405wrap f form =
401406 FormBuilder \props value ->
402407 let
403408 { edit, validate } = un FormBuilder form props value
404409 in
405410 { edit:
406− \k ->
407− pure
408− $ Wrapper
409− { key: Nothing
410− , wrap: f
411− , children: edit k
412− }
411+ \k ->
412+ pure
413+ $ Wrapper
414+ { key: Nothing
415+ , wrap: f
416+ , children: edit k
417+ }
413418 , validate
414419 }
415420
416421-- | Filter parts of the form based on the current value (and the props).
417−filterWithProps ∷
418− ∀ ui props u a.
419− Monoid ui =>
420− (props -> u -> Boolean) ->
421− FormBuilder' ui props u a ->
422− FormBuilder' ui props u a
422+filterWithProps
423+ ∷ ∀ ui props u a
424+ . Monoid ui
425+ => (props -> u -> Boolean)
426+ -> FormBuilder' ui props u a
427+ -> FormBuilder' ui props u a
423428filterWithProps p editor =
424429 FormBuilder \props value ->
425430 let
426431 { edit, validate } = un FormBuilder editor props value
427432 in
428433 { edit:
429− \onChange ->
430− if p props value then
431− edit onChange
432− else
433− mempty
434+ \onChange ->
435+ if p props value then
436+ edit onChange
437+ else
438+ mempty
434439 , validate
435440 }
436441
437442-- | TODO: document
438−withKey ∷
439− ∀ props u a.
440− String ->
441− FormBuilder props u a ->
442− FormBuilder props u a
443+withKey
444+ ∷ ∀ props u a
445+ . String
446+ -> FormBuilder props u a
447+ -> FormBuilder props u a
443448withKey key editor =
444449 FormBuilder \props value ->
445450 let
446451 { edit, validate } = un FormBuilder editor props value
447452 in
448453 { edit:
449− \onChange ->
450− edit onChange
451− # Array.mapWithIndex case _, _ of
452− i, Child a -> Child a { key = Just (key <> "--" <> show i) }
453− i, Wrapper a -> Wrapper a { key = Just (key <> "--" <> show i) }
454− i, Node n -> Node n { key = Just (key <> "--" <> show i) }
454+ \onChange ->
455+ edit onChange
456+ # Array.mapWithIndex case _, _ of
457+ i, Child a -> Child a { key = Just (key <> "--" <> show i) }
458+ i, Wrapper a -> Wrapper a { key = Just (key <> "--" <> show i) }
459+ i, Node n -> Node n { key = Just (key <> "--" <> show i) }
455460 , validate
456461 }
457462
@@ -465,57 +470,61 @@ type ValidatedInputFixedProps =
465470 , trailing ∷ JSX
466471 )
467472
468−inputBox ∷
469− ∀ p q r more.
470− Union p ValidatedInputFixedProps q =>
471− Union q r Input.Props =>
472− Nub q q =>
473− NonEmptyString -> RequiredField -> Record p -> FormBuilder { readOnly ∷ Boolean, validationError ∷ Maybe (Maybe String) | more } String String
473+inputBox
474+ ∷ ∀ p q r more
475+ . Union p ValidatedInputFixedProps q
476+ => Union q r Input.Props
477+ => Nub q q
478+ => NonEmptyString
479+ -> RequiredField
480+ -> Record p
481+ -> FormBuilder { readOnly ∷ Boolean, validationError ∷ Maybe (Maybe String) | more } String String
474482inputBox label requiredField inputProps =
475483 FormBuilder \props value ->
476484 let
477485 { edit, validate } = f props value
478486 in
479487 { edit:
480− \onChange ->
481− [ Child
482− { key: Nothing
483− , child: edit onChange
484− }
485− ]
488+ \onChange ->
489+ [ Child
490+ { key: Nothing
491+ , child: edit onChange
492+ }
493+ ]
486494 , validate
487495 }
488496 where
489497 f { readOnly, validationError } s =
490498 { edit:
491− \onChange ->
492− R.div' </* { className: "ry-form-input-box", css: E.css { width: E.percent 100.0 } }
493− /> [ element Input.component
494− ( inputProps
495− `disjointUnion`
496− { value: s
497− , onChange: handler targetValue (traverse_ (onChange <<< const))
498− , readOnly: readOnly
499− , label
500− , trailing:
501− case validationError of
502− Nothing -> mempty
503− Just (Just _) -> Block.icon </> { icon: Icons.warn, stroke: E.str colour.invalid }
504− Just Nothing -> Block.icon </> { icon: Icons.checkmark, stroke: E.str colour.success }
505− , _aria:
506− ( case validationError of
507− Nothing {- not validated yet -} -> mempty
508− Just Nothing {- validated and fine -} -> mempty --Object.singleton "invalid" "false"
509− Just (Just _) {- validated with an error -} -> Object.singleton "invalid" "true"
510− )
511− <> case requiredField of
512− Required -> Object.singleton "required" "true"
513− Optional -> mempty
514− Neither -> mempty
515− , css: E.css { width: E.percent 100.0 }
516− }
517− )
518− ]
499+ \onChange ->
500+ R.div' </* { className: "ry-form-input-box", css: E.css { width: E.percent 100.0 } }
501+ />
502+ [ element Input.component
503+ ( inputProps
504+ `disjointUnion`
505+ { value: s
506+ , onChange: handler targetValue (traverse_ (onChange <<< const))
507+ , readOnly: readOnly
508+ , label
509+ , trailing:
510+ case validationError of
511+ Nothing -> mempty
512+ Just (Just _) -> Block.icon </> { icon: Icons.warn, stroke: E.str colour.invalid }
513+ Just Nothing -> Block.icon </> { icon: Icons.checkmark, stroke: E.str colour.success }
514+ , _aria:
515+ ( case validationError of
516+ Nothing {- not validated yet -} -> mempty
517+ Just Nothing {- validated and fine -} -> mempty --Object.singleton "invalid" "false"
518+ Just (Just _) {- validated with an error -} -> Object.singleton "invalid" "true"
519+ )
520+ <> case requiredField of
521+ Required -> Object.singleton "required" "true"
522+ Optional -> mempty
523+ Neither -> mempty
524+ , css: E.css { width: E.percent 100.0 }
525+ }
526+ )
527+ ]
519528 , validate: pure s
520529 }
521530
@@ -526,25 +535,26 @@ type ToggleFixedProps =
526535 )
527536
528537-- | A toggle for Boolean values
529−toggle ∷
530− ∀ p q r more.
531− Union p ToggleFixedProps q =>
532− Union q r Toggle.Props =>
533− Nub q q =>
534− (Record p) -> FormBuilder { readOnly ∷ Boolean | more } Boolean Boolean
538+toggle
539+ ∷ ∀ p q r more
540+ . Union p ToggleFixedProps q
541+ => Union q r Toggle.Props
542+ => Nub q q
543+ => (Record p)
544+ -> FormBuilder { readOnly ∷ Boolean | more } Boolean Boolean
535545toggle toggleProps =
536546 formBuilder_ \{ readOnly } value onChange ->
537547 element Toggle.component
538548 ( toggleProps
539549 `disjointUnion`
540550 { value:
541− case value of
542− false -> ToggleIsLeft
543− true -> ToggleIsRight
551+ case value of
552+ false -> ToggleIsLeft
553+ true -> ToggleIsRight
544554 , onChange:
545− case _ of
546− ToggleIsLeft -> onChange false
547− ToggleIsRight -> onChange true
555+ case _ of
556+ ToggleIsLeft -> onChange false
557+ ToggleIsRight -> onChange true
548558 , disabled: readOnly
549559 }
550560 )
@@ -553,14 +563,14 @@ toggle toggleProps =
553563-- |
554564-- | This `FormBuilder` displays a removable section for each array element,
555565-- | along with an "Add..." button in the final row.
556−array ∷
557− ∀ props u a.
558− { label ∷ String
559− , addLabel ∷ String
560− , defaultValue ∷ u
561− , editor ∷ FormBuilder { readOnly ∷ Boolean | props } u a
562− } ->
563− FormBuilder { readOnly ∷ Boolean | props } (Array u) (Array a)
566+array
567+ ∷ ∀ props u a
568+ . { label ∷ String
569+ , addLabel ∷ String
570+ , defaultValue ∷ u
571+ , editor ∷ FormBuilder { readOnly ∷ Boolean | props } u a
572+ }
573+ -> FormBuilder { readOnly ∷ Boolean | props } (Array u) (Array a)
564574array { label, addLabel, defaultValue, editor } =
565575 FormBuilder \props@{ readOnly } xs ->
566576 let
@@ -569,52 +579,54 @@ array { label, addLabel, defaultValue, editor } =
569579 [ Wrapper
570580 { key: Nothing
571581 , wrap:
572− Block.box { style: R.css { paddingTop: 0 } }
582+ Block.box { style: R.css { paddingTop: 0 } }
573583 , children
574584 }
575585 ]
576586 in
577587 { edit:
578− \onChange -> do
579− let
580− deleteButton i =
581− R.a'
582− </ { onClick:
583− handler preventDefault
584− $ const
585− $ onChange (\xs' -> fromMaybe xs' (Array.deleteAt i xs'))
586− }
587− /> [ R.text "×" ]
588− wrapper $ xs
589− # Array.mapWithIndex
590− ( \i x ->
591− Node
592− { label:
593− fragment
594− [ if readOnly then empty else deleteButton i
595− , R.text $ " " <> label <> " #" <> show (i + 1)
596− ]
597− , key: Nothing
598− , required: Neither
599− , validationError: Nothing
600− , children: (un FormBuilder editor props x).edit (onChange <<< editAt i)
601− }
602− )
603− # if readOnly then
604− identity
605− else
606− flip Array.snoc
607− ( Child
608− { key: Nothing
609− , child:
610− Block.cluster { justify: "flex-end" }
611− /> [ Block.button
612− { onClick: handler preventDefault (const (onChange $ flip append [ defaultValue ]))
613− }
614− [ R.text $ "+ " <> addLabel ]
615− ]
616− }
588+ \onChange -> do
589+ let
590+ deleteButton i =
591+ R.a'
592+ </
593+ { onClick:
594+ handler preventDefault
595+ $ const
596+ $ onChange (\xs' -> fromMaybe xs' (Array.deleteAt i xs'))
597+ }
598+ /> [ R.text "×" ]
599+ wrapper $ xs
600+ # Array.mapWithIndex
601+ ( \i x ->
602+ Node
603+ { label:
604+ fragment
605+ [ if readOnly then empty else deleteButton i
606+ , R.text $ " " <> label <> " #" <> show (i + 1)
607+ ]
608+ , key: Nothing
609+ , required: Neither
610+ , validationError: Nothing
611+ , children: (un FormBuilder editor props x).edit (onChange <<< editAt i)
612+ }
617613 )
614+ #
615+ if readOnly then identity
616+ else
617+ flip Array.snoc
618+ ( Child
619+ { key: Nothing
620+ , child:
621+ Block.cluster { justify: "flex-end" }
622+ />
623+ [ Block.button
624+ { onClick: handler preventDefault (const (onChange $ flip append [ defaultValue ]))
625+ }
626+ [ R.text $ "+ " <> addLabel ]
627+ ]
628+ }
629+ )
618630 , validate: traverse (un FormBuilder editor props >>> _.validate) xs
619631 }
620632
@@ -622,43 +634,43 @@ array { label, addLabel, defaultValue, editor } =
622634-- |
623635-- | This `FormBuilder` displays a removable section for each array element,
624636-- | along with an "Add..." button in the final row.
625−sortableArray ∷
626− ∀ props u a.
627− { label ∷ String
628− , addLabel ∷ String
629− , defaultValue ∷ u
630− , editor ∷ FormBuilder { readOnly ∷ Boolean | props } u a
631− } ->
632− FormBuilder { readOnly ∷ Boolean | props } (Array u) (Array a)
637+sortableArray
638+ ∷ ∀ props u a
639+ . { label ∷ String
640+ , addLabel ∷ String
641+ , defaultValue ∷ u
642+ , editor ∷ FormBuilder { readOnly ∷ Boolean | props } u a
643+ }
644+ -> FormBuilder { readOnly ∷ Boolean | props } (Array u) (Array a)
633645sortableArray { label, addLabel, defaultValue, editor } =
634646 FormBuilder \props@{ readOnly } xs -> do
635647 { edit:
636− \(onChange ∷ (Array u -> Array u) -> Effect Unit) -> do
637− let
638− addButton =
639− Block.cluster { justify: "flex-end" }
640− [ Block.button
641− { onClick: handler preventDefault (const (onChange $ flip append [ defaultValue ]))
642− , disabled: readOnly
643− }
644− [ R.text $ "+ " <> addLabel ]
645− ]
646− appendAddButton items =
647− if readOnly then
648− items
649− else
650− Array.snoc items $ Child { key: Nothing, child: addButton }
651− mkNode i x =
652− Node
653− { label: R.text $ " " <> label <> " #" <> show (i + 1)
654− , key: Nothing
655− , required: Neither
656− , validationError: Nothing
657− , children: (un FormBuilder editor props x).edit (onChange <<< editAt i)
658− }
659− wrapper readOnly onChange $ xs
660− # Array.mapWithIndex mkNode
661− # appendAddButton
648+ \(onChange ∷ (Array u -> Array u) -> Effect Unit) -> do
649+ let
650+ addButton =
651+ Block.cluster { justify: "flex-end" }
652+ [ Block.button
653+ { onClick: handler preventDefault (const (onChange $ flip append [ defaultValue ]))
654+ , disabled: readOnly
655+ }
656+ [ R.text $ "+ " <> addLabel ]
657+ ]
658+ appendAddButton items =
659+ if readOnly then
660+ items
661+ else
662+ Array.snoc items $ Child { key: Nothing, child: addButton }
663+ mkNode i x =
664+ Node
665+ { label: R.text $ " " <> label <> " #" <> show (i + 1)
666+ , key: Nothing
667+ , required: Neither
668+ , validationError: Nothing
669+ , children: (un FormBuilder editor props x).edit (onChange <<< editAt i)
670+ }
671+ wrapper readOnly onChange $ xs
672+ # Array.mapWithIndex mkNode
673+ # appendAddButton
662674 , validate: traverse (un FormBuilder editor props >>> _.validate) xs
663675 }
664676 where
@@ -668,69 +680,74 @@ sortableArray { label, addLabel, defaultValue, editor } =
668680 [ Wrapper
669681 { key: Nothing
670682 , wrap:
671− \kids ->
672− Block.box { style: R.css { paddingTop: 0 } }
673− [ formArray </> { kids, onChange, readOnly } ]
683+ \kids ->
684+ Block.box { style: R.css { paddingTop: 0 } }
685+ [ formArray </> { kids, onChange, readOnly } ]
674686 , children
675687 }
676688 ]
677689
678690 formArray =
679691 unsafePerformEffect
680− $ reactComponent "Form Array" \( props ∷
681− { kids ∷ Array JSX
682− , onChange ∷ (Array u -> Array u) -> Effect Unit
683− , readOnly ∷ Boolean
684− }
685− ) -> Hooks.do
686− let children = if props.readOnly then props.kids else Array.dropEnd 1 props.kids
687− let addButton = guard (not props.readOnly) (Array.last props.kids # Array.fromFoldable)
688− items /\ setItems <- Hooks.useState' []
689− currentKeyRef <- Hooks.useRef 0
690− let numberOfChildren = Array.length children
691− let numberOfItems = Array.length items
692− useEffect numberOfChildren do
693− when (numberOfChildren > numberOfItems) do
694− currentKey <- Hooks.readRef currentKeyRef
695− let newKey = currentKey + 1
696− Hooks.writeRef currentKeyRef newKey
697− setItems (Array.snoc items (show newKey))
698− mempty
699− let
700− onDragEnd =
701− handler (merge { active: Dnd.active, over: Dnd.over }) case _ of
702− { active: Just active, over: Just over } ->
703− when (active.id /= over.id) do
704− case Array.findIndex (_ == active.id) items, Array.findIndex (_ == over.id) items of
705− Just oldIndex, Just newIndex -> do
706− setItems $ Dnd.arrayMove oldIndex newIndex items
707− props.onChange (\xs' -> Dnd.arrayMove oldIndex newIndex xs')
708− _, _ -> mempty
709− _ -> mempty
710− pure $ Dnd.dndContext
711− </ { collisionDetection: Dnd.closestCenter
712− , onDragEnd
713− }
714− /> [ Dnd.sortableContext
715− </ { items
716− , strategy: Dnd.verticalListSortingStrategy
717− }
718− /> ( Array.zip children items
719− # Array.mapWithIndex case _, _ of
720− i, kid /\ id -> do
721− Hooks.elementKeyed itemComponent
722− { id
723− , kid
724− , key: id
725− , readOnly: props.readOnly
726− , delete:
727− do
728− props.onChange \xs' -> fromMaybe xs' (Array.deleteAt i xs')
729− setItems $ fromMaybe items (Array.deleteAt i items)
730− }
731− )
732− ]
733− <> addButton
692+ $ reactComponent "Form Array"
693+ \( props
694+ ∷ { kids ∷ Array JSX
695+ , onChange ∷ (Array u -> Array u) -> Effect Unit
696+ , readOnly ∷ Boolean
697+ }
698+ ) -> Hooks.do
699+ let children = if props.readOnly then props.kids else Array.dropEnd 1 props.kids
700+ let addButton = guard (not props.readOnly) (Array.last props.kids # Array.fromFoldable)
701+ items /\ setItems <- Hooks.useState' []
702+ currentKeyRef <- Hooks.useRef 0
703+ let numberOfChildren = Array.length children
704+ let numberOfItems = Array.length items
705+ useEffect numberOfChildren do
706+ when (numberOfChildren > numberOfItems) do
707+ currentKey <- Hooks.readRef currentKeyRef
708+ let newKey = currentKey + 1
709+ Hooks.writeRef currentKeyRef newKey
710+ setItems (Array.snoc items (show newKey))
711+ mempty
712+ let
713+ onDragEnd =
714+ handler (merge { active: Dnd.active, over: Dnd.over }) case _ of
715+ { active: Just active, over: Just over } ->
716+ when (active.id /= over.id) do
717+ case Array.findIndex (_ == active.id) items, Array.findIndex (_ == over.id) items of
718+ Just oldIndex, Just newIndex -> do
719+ setItems $ Dnd.arrayMove oldIndex newIndex items
720+ props.onChange (\xs' -> Dnd.arrayMove oldIndex newIndex xs')
721+ _, _ -> mempty
722+ _ -> mempty
723+ pure $ Dnd.dndContext
724+ </
725+ { collisionDetection: Dnd.closestCenter
726+ , onDragEnd
727+ }
728+ />
729+ [ Dnd.sortableContext
730+ </
731+ { items
732+ , strategy: Dnd.verticalListSortingStrategy
733+ }
734+ />
735+ ( Array.zip children items
736+ # Array.mapWithIndex case _, _ of
737+ i, kid /\ id -> do
738+ Hooks.elementKeyed itemComponent
739+ { id
740+ , kid
741+ , key: id
742+ , readOnly: props.readOnly
743+ , delete:
744+ do
745+ props.onChange \xs' -> fromMaybe xs' (Array.deleteAt i xs')
746+ setItems $ fromMaybe items (Array.deleteAt i items)
747+ }
748+ )
749+ ]
750+ <> addButton
734751
735752 itemComponent =
736753 unsafePerformEffect
@@ -743,7 +760,6 @@ sortableArray { label, addLabel, defaultValue, editor } =
743760 } <-
744761 Dnd.useSortable { id: props.id }
745762 showMenu /\ setShowMenu <- Hooks.useState' false
746− referenceElement /\ setReferenceElement <- Hooks.useState' nullRef
747763 let
748764 style =
749765 R.css
@@ -754,23 +770,23 @@ sortableArray { label, addLabel, defaultValue, editor } =
754770 }
755771 attrs =
756772 RB.build
757− -- RB.disjointUnion listeners >>>
773+ -- RB.disjointUnion listeners >>>
758774 ( RB.disjointUnion attributes
759775 )
760776 { ref: setNodeRef
761777 , style
762778 , css:
763− E.css
764− { "&:focus":
765− E.nested
766− $ E.css
767− { outlineColor: E.str colour.highlight
768− }
769− , transition: E.str "box-shadow 0.8s ease"
770− , position: E.relative
771− , boxSizing: E.contentBox
772− , overflow: E.visible
773− }
779+ E.css
780+ { "&:focus":
781+ E.nested
782+ $ E.css
783+ { outlineColor: E.str colour.highlight
784+ }
785+ , transition: E.str "box-shadow 0.8s ease"
786+ , position: E.relative
787+ , boxSizing: E.contentBox
788+ , overflow: E.visible
789+ }
774790 , className: "ry-draggable-array-element"
775791 }
776792 circleStyle =
@@ -796,8 +812,8 @@ sortableArray { label, addLabel, defaultValue, editor } =
796812 )
797813 { className: "ry-draggable-array-drag-handle"
798814 , css:
799− circleStyle
800− <> E.css
815+ circleStyle
816+ <> E.css
801817 { right: E.str "var(--s-1)"
802818 , cursor: E.str "grab"
803819 }
@@ -808,8 +824,8 @@ sortableArray { label, addLabel, defaultValue, editor } =
808824 deleteButtonAttrs =
809825 { className: "ry-draggable-array-delete-button"
810826 , css:
811− circleStyle
812− <> E.css
827+ circleStyle
828+ <> E.css
813829 { right: E.str "calc(var(--s-1) + var(--s-1) + var(--s2) + var(--s-3))"
814830 }
815831 , onClick: handler preventDefault (const props.delete)
@@ -820,32 +836,17 @@ sortableArray { label, addLabel, defaultValue, editor } =
820836 menuButtonAttrs =
821837 { className: "ry-draggable-array-delete-button"
822838 , css:
823− circleStyle
824− <> E.css
839+ circleStyle
840+ <> E.css
825841 { right: E.str "calc(var(--s-1) + var(--s-1) + var(--s2) + var(--s-3))"
826842 }
827843 , onClick: handler_ (setShowMenu (not showMenu))
828− , ref: unsafeCoerce $ mkEffectFn1 setReferenceElement
829844 }
830845 menuIcon = Block.icon </> { icon: Icons.ellipsis, size: E.str "var(--s1)", colour: E.str colour.text }
831846 menuButton = if props.readOnly then empty else R.div' </* menuButtonAttrs /> [ menuIcon ]
832− menuPopover =
833− if showMenu then
834− Block.popover
835− </ { referenceElement
836− -- , placement: Placement.Placement Placement.Bottom (Just Placement.End)
837− , renderArrow: true
838− }
839− /> [ Block.box {}
840− [ R.text "Sure?"
841− , deleteButton
842− ]
843− ]
844− else
845− mempty
846847 pure $ R.li' </* attrs
847− /> [ dragHandle
848+ />
849+ [ dragHandle
848850 , menuButton
849− , menuPopover
850851 , props.kid
851852 ]
src/Yoga/Block/Organism/Form/Internal.purs+68−66
@@ -2,7 +2,9 @@
22module Yoga.Block.Organism.Form.Internal where
33
44import Yoga.Prelude.View
5−import Control.MonadZero (class Alt, class Alternative, class Plus)
5+
6+import Control.Alt (class Alt)
7+import Control.Alternative (class Alternative, class Plus)
68import Data.Array as Array
79import Data.Either (either)
810import Data.Newtype (class Newtype, un)
@@ -12,21 +14,21 @@ import Yoga.Block.Organism.Form.Types (RequiredField)
1214
1315data Tree
1416 = Child
15− { key ∷ Maybe String
16− , child ∷ JSX
17− }
17+ { key ∷ Maybe String
18+ , child ∷ JSX
19+ }
1820 | Wrapper
19− { key ∷ Maybe String
20− , wrap ∷ Array JSX -> JSX
21− , children ∷ Forest
22− }
21+ { key ∷ Maybe String
22+ , wrap ∷ Array JSX -> JSX
23+ , children ∷ Forest
24+ }
2325 | Node
24− { label ∷ JSX
25− , key ∷ Maybe String
26− , required ∷ RequiredField
27− , validationError ∷ Maybe String
28− , children ∷ Forest
29− }
26+ { label ∷ JSX
27+ , key ∷ Maybe String
28+ , required ∷ RequiredField
29+ , validationError ∷ Maybe String
30+ , children ∷ Forest
31+ }
3032
3133type Forest =
3234 Array Tree
@@ -60,11 +62,11 @@ pruneTree = case _ of
6062-- | An applicative functor which can be used to build forms.
6163-- | Forms can be turned into components using the `build` function.
6264newtype FormBuilder' ui props unvalidated result = FormBuilder
63− ( props {- ^ additional props -} ->
64− unvalidated {- ^ the current value -} ->
65− { edit ∷ ((unvalidated -> unvalidated) -> Effect Unit) -> ui
66− , validate ∷ Maybe result
67− }
65+ ( props {- ^ additional props -}
66+ -> unvalidated {- ^ the current value -}
67+ -> { edit ∷ ((unvalidated -> unvalidated) -> Effect Unit) -> ui
68+ , validate ∷ Maybe result
69+ }
6870 )
6971
7072type FormBuilder props unvalidated result =
@@ -94,13 +96,13 @@ parallel key (SeqFormBuilder (FormBuilder f)) =
9496 FormBuilder \props value -> do
9597 let { edit, validate } = f props value
9698 { edit:
97− \onChange ->
98− [ Wrapper
99− { key: Just key
100− , wrap: keyed key <<< fragment
101− , children: edit onChange
102− }
103− ]
99+ \onChange ->
100+ [ Wrapper
101+ { key: Just key
102+ , wrap: keyed key <<< fragment
103+ , children: edit onChange
104+ }
105+ ]
104106 , validate: validate
105107 }
106108
@@ -110,13 +112,13 @@ sequential key (FormBuilder f) =
110112 $ FormBuilder \props value -> do
111113 let { edit, validate } = f props value
112114 { edit:
113− \onChange ->
114− [ Wrapper
115− { key: Just key
116− , wrap: keyed key <<< fragment
117− , children: edit onChange
118− }
119− ]
115+ \onChange ->
116+ [ Wrapper
117+ { key: Just key
118+ , wrap: keyed key <<< fragment
119+ , children: edit onChange
120+ }
121+ ]
120122 , validate
121123 }
122124
@@ -174,37 +176,37 @@ instance alternativeSeqFormBuilder ∷ Monoid ui => Alternative (SeqFormBuilder'
174176
175177-- | Create a `FormBuilder` from a function which produces a form
176178-- | element as `JSX` and a validated result.
177−formBuilder ∷
178− ∀ props unvalidated a.
179− ( props ->
180− unvalidated ->
181− { edit ∷ ((unvalidated -> unvalidated) -> Effect Unit) -> JSX
182− , validate ∷ Maybe a
183− }
184− ) ->
185− FormBuilder props unvalidated a
179+formBuilder
180+ ∷ ∀ props unvalidated a
181+ . ( props
182+ -> unvalidated
183+ -> { edit ∷ ((unvalidated -> unvalidated) -> Effect Unit) -> JSX
184+ , validate ∷ Maybe a
185+ }
186+ )
187+ -> FormBuilder props unvalidated a
186188formBuilder f =
187189 FormBuilder \props value ->
188190 let
189191 { edit, validate } = f props value
190192 in
191193 { edit:
192− \onChange ->
193− [ Child
194− { key: Nothing
195− , child: edit onChange
196− }
197− ]
194+ \onChange ->
195+ [ Child
196+ { key: Nothing
197+ , child: edit onChange
198+ }
199+ ]
198200 , validate: validate
199201 }
200202
201203-- | The simplest way to create a `FormBuilder`. Create a `FormBuilder`
202204-- | provided a function that, given the current value and a change callback,
203205-- | renders a form element as `JSX`.
204−formBuilder_ ∷
205− ∀ props a.
206− (props -> a -> (a -> Effect Unit) -> JSX) ->
207− FormBuilder props a a
206+formBuilder_
207+ ∷ ∀ props a
208+ . (props -> a -> (a -> Effect Unit) -> JSX)
209+ -> FormBuilder props a a
208210formBuilder_ f =
209211 formBuilder \props value ->
210212 { edit: f props value <<< (_ <<< const)
@@ -222,29 +224,29 @@ invalidate (FormBuilder f) =
222224
223225-- | Revalidate the form, in order to display error messages or create
224226-- | a validated result.
225−revalidate ∷
226− ∀ ui props unvalidated result.
227− FormBuilder' ui props unvalidated result ->
228− props ->
229− unvalidated ->
230− Maybe result
227+revalidate
228+ ∷ ∀ ui props unvalidated result
229+ . FormBuilder' ui props unvalidated result
230+ -> props
231+ -> unvalidated
232+ -> Maybe result
231233revalidate editor props value = (un FormBuilder editor props value).validate
232234
233235-- | Listens for changes in a form's value and allows for performing
234236-- | asynchronous effects and additional value changes.
235−listen ∷
236− ∀ ui props unvalidated result.
237− (unvalidated -> Aff (unvalidated -> unvalidated)) ->
238− FormBuilder' ui props unvalidated result ->
239− FormBuilder' ui props unvalidated result
237+listen
238+ ∷ ∀ ui props unvalidated result
239+ . (unvalidated -> Aff (unvalidated -> unvalidated))
240+ -> FormBuilder' ui props unvalidated result
241+ -> FormBuilder' ui props unvalidated result
240242listen cb (FormBuilder f) =
241243 FormBuilder \props unvalidated ->
242244 let
243245 { edit, validate } = f props unvalidated
244246 in
245247 { edit:
246− \onChange ->
247− edit \update ->
248− runAff_ (either throwException onChange) (map (_ <<< update) (cb (update unvalidated)))
248+ \onChange ->
249+ edit \update ->
250+ runAff_ (either throwException onChange) (map (_ <<< update) (cb (update unvalidated)))
249251 , validate
250252 }
src/Yoga/Block/Organism/Form/Story.purs+27−21
@@ -1,6 +1,7 @@
11module Yoga.Block.Organism.Form.Story where
22
33import Prelude
4+
45import Data.Lens.Record (prop)
56import Data.Maybe (Maybe(..))
67import Data.String.NonEmpty (NonEmptyString, nes)
@@ -17,26 +18,29 @@ import React.Basic.Hooks as React
1718import Type.Prelude (Proxy(..))
1819import Yoga ((/>), (</), (</>))
1920import Yoga.Block as Block
21+import Yoga.Block.Atom.Input.Hook.UseTypingPlaceholders (useTypingPlaceholders)
2022import Yoga.Block.Atom.Input.Types as InputType
2123import Yoga.Block.Container.Style as Styles
24+import Yoga.Block.Internal (NodeRef)
2225import Yoga.Block.Organism.Form (FormBuilder, Validated(..), formDefaults)
2326import Yoga.Block.Organism.Form as Form
2427import Yoga.Block.Organism.Form.Types (RequiredField(..))
2528
26−default ∷
27− { decorators ∷ Array (Effect JSX -> JSX)
28− , title ∷ String
29− }
29+default
30+ ∷ { decorators ∷ Array (Effect JSX -> JSX)
31+ , title ∷ String
32+ }
3033default =
3134 { title: "Organism/Form"
3235 , decorators:
33− [ \storyFn ->
34− Block.container
35− </ {}
36− /> [ element E.global { styles: Styles.global }
37− , unsafePerformEffect storyFn
38− ]
39− ]
36+ [ \storyFn ->
37+ Block.container
38+ </ {}
39+ />
40+ [ element E.global { styles: Styles.global }
41+ , unsafePerformEffect storyFn
42+ ]
43+ ]
4044 }
4145
4246type User =
@@ -72,13 +76,15 @@ aForm = do
7276 where
7377 mkExample =
7478 reactComponent "FormExample" \_ -> React.do
79+ inputRef ← useTypingPlaceholders "First name"
80+ [ "Type in your given name", "WAAAAARUMÄ" ]
7581 _userDialog /\ setUserDialog <- useState' Nothing
7682 { setModified, reset: _reset, validated, form } <-
77− Form.useForm userForm
83+ Form.useForm (userForm inputRef)
7884 { initialState: formDefaults
7985 , formProps:
80− { readOnly: false
81− }
86+ { readOnly: false
87+ }
8288 }
8389 pure
8490 $ fragment
@@ -87,10 +93,10 @@ aForm = do
8793 -- on the form's submit button and `preventDefault` to keep the browser
8894 -- from reloading the page on submission.
8995 { onSubmit:
90− handler preventDefault \_ -> case validated of
91− Nothing -> do
92− setModified
93− Just { firstName, lastName } -> setUserDialog $ Just { firstName, lastName }
96+ handler preventDefault \_ -> case validated of
97+ Nothing -> do
98+ setModified
99+ Just { firstName, lastName } -> setUserDialog $ Just { firstName, lastName }
94100 , style: R.css { alignSelf: "stretch" }
95101 , children: [ form ]
96102 }
@@ -123,13 +129,13 @@ aForm = do
123129 }
124130 in { nickname, age }
125131
126− userForm ∷ ∀ props. FormBuilder { readOnly ∷ Boolean | props } User ValidUser
127− userForm = ado
132+ userForm ∷ ∀ props. NodeRef -> FormBuilder { readOnly ∷ Boolean | props } User ValidUser
133+ userForm inputRef = ado
128134 firstName <-
129135 Form.focus (prop (Proxy ∷ _ "firstName"))
130136 $ Form.validated (Form.nonEmpty' "You must have a first name")
131137 $ Form.inputBox (nes (Proxy ∷ _ "First Name")) Required
132− { placeholder: "First name" }
138+ { id: "firstName", inputRef }
133139 lastName <-
134140 Form.focus (prop (Proxy ∷ _ "lastName"))
135141 $ Form.validated
src/Yoga/Block/Organism/Form/Validation.purs+111−95
@@ -130,30 +130,36 @@ validNumber name = validNumber' (name <> " must be a number")
130130validNumber' ∷ String -> Validator String Number
131131validNumber' msg = note msg <<< Number.fromString
132132
133−-- | A `Validator`, which ensures a number is inclusively between two positive
133+-- | A `Validator`, which ensures a number is inclusively between two positive
134134-- | integers
135−validNatBetween ∷
136− ∀ minStr maxStr min max subtracted.
137− Peano.ParseNat minStr min =>
138− Peano.ParseNat maxStr max =>
139− Peano.IsNat min =>
140− Peano.IsNat max =>
141− Peano.IsNat subtracted =>
142− Peano.SumInt (Peano.Pos max) (Peano.Neg min) (Peano.Pos subtracted) =>
143− Proxy minStr -> Proxy maxStr -> String -> Validator String Int
135+validNatBetween
136+ ∷ ∀ minStr maxStr min max subtracted
137+ . Peano.ParseNat minStr min
138+ => Peano.ParseNat maxStr max
139+ => Peano.IsNat min
140+ => Peano.IsNat max
141+ => Peano.IsNat subtracted
142+ => Peano.SumInt (Peano.Pos max) (Peano.Neg min) (Peano.Pos subtracted)
143+ => Proxy minStr
144+ -> Proxy maxStr
145+ -> String
146+ -> Validator String Int
144147validNatBetween minProxy maxProxy name = do
145148 validNatBetween' minProxy maxProxy \min max ->
146149 name <> " must be between " <> show min <> " and " <> show max
147150
148−validNatBetween' ∷
149− ∀ minSymbol maxSymbol min max subtracted.
150− Peano.ParseNat minSymbol min =>
151− Peano.ParseNat maxSymbol max =>
152− Peano.IsNat min =>
153− Peano.IsNat max =>
154− Peano.IsNat subtracted =>
155− Peano.SumInt (Peano.Pos max) (Peano.Neg min) (Peano.Pos subtracted) =>
156− Proxy minSymbol -> Proxy maxSymbol -> (Int -> Int -> String) -> Validator String Int
151+validNatBetween'
152+ ∷ ∀ minSymbol maxSymbol min max subtracted
153+ . Peano.ParseNat minSymbol min
154+ => Peano.ParseNat maxSymbol max
155+ => Peano.IsNat min
156+ => Peano.IsNat max
157+ => Peano.IsNat subtracted
158+ => Peano.SumInt (Peano.Pos max) (Peano.Neg min) (Peano.Pos subtracted)
159+ => Proxy minSymbol
160+ -> Proxy maxSymbol
161+ -> (Int -> Int -> String)
162+ -> Validator String Int
157163validNatBetween' minSymbolProxy maxSymbolProxy msg rawString = case Int.fromString rawString of
158164 Just parseableInt
159165 | between minInt maxInt parseableInt -> Right parseableInt
@@ -259,20 +265,20 @@ _Modified =
259265
260266-- | Sets all `Validated` fields in a record to `Fresh`, hiding all validation
261267-- | messages.
262−setFresh ∷
263− ∀ value.
264− Mapping ModifyValidated value value =>
265− value ->
266− value
268+setFresh
269+ ∷ ∀ value
270+ . Mapping ModifyValidated value value
271+ => value
272+ -> value
267273setFresh = mapping (ModifyValidated (Fresh <<< view _Validated))
268274
269275-- | Sets all `Validated` fields in a record to `Modified`, showing all
270276-- | validation messages.
271−setModified ∷
272− ∀ value.
273− Mapping ModifyValidated value value =>
274− value ->
275− value
277+setModified
278+ ∷ ∀ value
279+ . Mapping ModifyValidated value value
280+ => value
281+ -> value
276282setModified = mapping (ModifyValidated (Modified <<< view _Validated))
277283
278284-- | Internal utility type for modifying the validated state of fields in
@@ -308,7 +314,9 @@ class CustomModifyValidated a where
308314instance modifyValidated ∷ Mapping ModifyValidated a a => Mapping ModifyValidated (Validated a) (Validated a) where
309315 mapping m@(ModifyValidated f) = over _Validated (mapping m) <<< f
310316else instance modifyValidatedRecord ∷
311− (RL.RowToList r xs, MapRecordWithIndex xs (ConstMapping ModifyValidated) r r) =>
317+ ( RL.RowToList r xs
318+ , MapRecordWithIndex xs (ConstMapping ModifyValidated) r r
319+ ) =>
312320 Mapping ModifyValidated { | r } { | r } where
313321 mapping d = hmap d
314322else instance modifyValidatedArray ∷ Mapping ModifyValidated a a => Mapping ModifyValidated (Array a) (Array a) where
@@ -343,12 +351,12 @@ else instance canValidateAny ∷ CanValidate a a where
343351-- | This `Validated` data type describes a form field as either `Fresh` or
344352-- | `Modified`, so that validation messages are only displayed if the field
345353-- | is `Modified`.
346−validated ∷
347− ∀ props unvalidated validated result result_.
348− CanValidate unvalidated validated =>
349− Validator result_ result ->
350− FormBuilder { readOnly ∷ Boolean, validationError ∷ Maybe (Maybe String) | props } unvalidated result_ ->
351− FormBuilder { readOnly ∷ Boolean | props } (Validated validated) result
354+validated
355+ ∷ ∀ props unvalidated validated result result_
356+ . CanValidate unvalidated validated
357+ => Validator result_ result
358+ -> FormBuilder { readOnly ∷ Boolean, validationError ∷ Maybe (Maybe String) | props } unvalidated result_
359+ -> FormBuilder { readOnly ∷ Boolean | props } (Validated validated) result
352360validated runValidator editor =
353361 FormBuilder \props@{ readOnly } (v ∷ Validated validated) -> do
354362 let
@@ -359,16 +367,17 @@ validated runValidator editor =
359367 { className: "ry-form-inner-column"
360368 , space: E.str "0"
361369 , css:
362− E.css
363− { maxWidth: E.str "100%"
364− , margin: E.str "0"
365− }
370+ E.css
371+ { maxWidth: E.str "100%"
372+ , margin: E.str "0"
373+ }
366374 }
367375 -- validationMessage ∷ Maybe validated
368376 -- validationMessage = case v of
369377 -- Fresh _ -> Nothing
370378 -- Modified m -> Just m
371379 { validate } = un FormBuilder editor (props # upsert (Proxy ∷ _ "validationError") (Nothing)) value
380+
372381 modify ∷ Maybe String -> Forest -> Forest
373382 modify message forest = case Array.unsnoc forest of
374383 Nothing -> [ Child { key: Nothing, child: errChild } ]
@@ -379,6 +388,7 @@ validated runValidator editor =
379388 errLine = guard (not readOnly) message # foldMap R.text
380389
381390 errChild = errorChild </> { errorLine: errLine, message }
391+
382392 -- The validation can produce either a valid result, an error message, or
383393 -- none in the case where the form is Fresh.
384394 res ∷ Maybe (Either String result)
@@ -390,13 +400,13 @@ validated runValidator editor =
390400 err = either pure (const Nothing) =<< res
391401 finalResult = un FormBuilder editor (props # upsert (Proxy ∷ _ "validationError") (res <#> either Just (const Nothing))) value
392402 { edit:
393− \onChange ->
394− (modify err <<< finalResult.edit)
395− ( onChange
396− <<< \f -> case _ of
403+ \onChange ->
404+ (modify err <<< finalResult.edit)
405+ ( onChange
406+ <<< \f -> case _ of
397407 v'@(Fresh _) -> review modified (f (fromValidated v'))
398408 v'@(Modified _) -> review modified (f (fromValidated v'))
399− )
409+ )
400410 , validate: hush =<< res
401411 }
402412
@@ -408,75 +418,81 @@ errorChild =
408418 let
409419 variants =
410420 { hidden:
411− const
412− { y: "-100%"
413− , height: "auto"
421+ const
422+ { y: "-100%"
423+ , height: "auto"
424+ , transition: { type: "tween", delay: 0.75 }
425+ }
426+ , visible:
427+ { y: "0%"
414428 , transition: { type: "tween", delay: 0.75 }
415429 }
416− , visible:
417− { y: "0%"
418− , transition: { type: "tween", delay: 0.75 }
419− }
420430 }
421431 let variant = makeVariantLabels variants
422432 pure
423433 $ R.div'
424− </* { className: "ry-validation-error"
434+ </*
435+ { className: "ry-validation-error"
425436 , css:
426− E.css
427− { fontSize: E.str "calc(var(--s0) * 0.8)"
428− , fontWeight: E.str "400"
429− , height: E.str "calc(var(--s0) + var(--s-3))"
430− , margin: E.str "0 var(--s-1) 0 var(--s-1)"
431− , overflow: E.str $ if expanded then "visible" else "hidden"
432− }
437+ E.css
438+ { fontSize: E.str "calc(var(--s0) * 0.8)"
439+ , fontWeight: E.str "400"
440+ , height: E.str "calc(var(--s0) + var(--s-3))"
441+ , margin: E.str "0 var(--s-1) 0 var(--s-1)"
442+ , overflow: E.str $ if expanded then "visible" else "hidden"
443+ }
433444 }
434− /> [ Motion.animatePresence </ {}
445+ />
446+ [ Motion.animatePresence </ {}
435447 /> case message of
436− Just _ ->
437− [ Motion.div
438− </* { variants: Motion.variants variants
439− , initial: Motion.initial variant.hidden
440− , animate: Motion.animate variant.visible
441− , exit: Motion.exit $ variant.hidden
442− , className: "ry-validation-error"
443− , css:
448+ Just _ ->
449+ [ Motion.div
450+ </*
451+ { variants: Motion.variants variants
452+ , initial: Motion.initial variant.hidden
453+ , animate: Motion.animate variant.visible
454+ , exit: Motion.exit $ variant.hidden
455+ , className: "ry-validation-error"
456+ , css:
444457 E.css
445458 { color: E.str colour.invalidText
446459 , background: E.color Palette.pink.dark
447460 , padding: E.str "var(--s-5) var(--s-3) var(--s-4) var(--s-3)"
448461 , borderRadius: E.str "0 0 var(--s-3) var(--s-3)"
449462 }
450− }
451− /> [ motionReadMore
452− </ Motion.withMotion
453− { background: Palette.pink.dark
454− , onMoreClicked: setExpanded true
455− , onLessClicked: setExpanded false
456− }
457− { layout: Motion.layout false
458− }
459− /> [ R.span'
460− </* { className: "ry-validation-error"
461− , css: E.css {}
462− }
463− /> [ errorLine ]
464− ]
465− ]
466− ]
467− _ -> mempty
463+ }
464+ />
465+ [ motionReadMore
466+ </ Motion.withMotion
467+ { background: Palette.pink.dark
468+ , onMoreClicked: setExpanded true
469+ , onLessClicked: setExpanded false
470+ }
471+ { layout: Motion.layout false
472+ }
473+ />
474+ [ R.span'
475+ </*
476+ { className: "ry-validation-error"
477+ , css: E.css {}
478+ }
479+ /> [ errorLine ]
480+ ]
481+ ]
482+ ]
483+ _ -> mempty
468484 ]
469485 where
470486 motionReadMore = unsafePerformEffect $ Motion.custom Block.readMore
471487
472−upsert ∷
473− ∀ proxy r1 r2 r l a.
474− IsSymbol l =>
475− Cons l a r r2 =>
476− proxy l ->
477− a ->
478− Record r1 ->
479− Record r2
488+upsert
489+ ∷ ∀ r1 r2 r l a
490+ . IsSymbol l
491+ => Cons l a r r2
492+ => Proxy l
493+ -> a
494+ -> Record r1
495+ -> Record r2
480496upsert l a r = unsafeSet (reflectSymbol l) a r
481497
482498-- -- | Attach a validation function to a `FormBuilder p u a`, producing a new
src/Yoga/Block/Palette/Story.purs+24−20
@@ -19,10 +19,10 @@ import Yoga.Block.Layout.Box as Box
1919import Yoga.Block.Palette (ColourVariants)
2020import Yoga.Block.Palette as Palette
2121
22−default ∷
23− { decorators ∷ Array (Effect JSX -> JSX)
24− , title ∷ String
25− }
22+default
23+ ∷ { decorators ∷ Array (Effect JSX -> JSX)
24+ , title ∷ String
25+ }
2626default =
2727 { title: "Palette"
2828 , decorators:
@@ -39,16 +39,16 @@ box =
3939 pure
4040 $ fragment
4141 [ Block.grid { min: "100px" }
42− $ colourBoxes "Pink" Palette.pink
43− <> colourBoxes "Mauve" Palette.mauve
44− <> colourBoxes "Violet" Palette.violet
45− <> colourBoxes "Blue" Palette.blue
46− <> colourBoxes "Azure" Palette.azure
47− <> colourBoxes "Capri" Palette.capri
48− <> colourBoxes "Sea Green" Palette.seaGreen
49− <> colourBoxes "Malachite" Palette.malachite
50− <> colourBoxes "Yellow" Palette.yellow
51− <> colourBoxes "Mango" Palette.mango
42+ $ colourBoxes "Pink" Palette.pink
43+ <> colourBoxes "Mauve" Palette.mauve
44+ <> colourBoxes "Violet" Palette.violet
45+ <> colourBoxes "Blue" Palette.blue
46+ <> colourBoxes "Azure" Palette.azure
47+ <> colourBoxes "Capri" Palette.capri
48+ <> colourBoxes "Sea Green" Palette.seaGreen
49+ <> colourBoxes "Malachite" Palette.malachite
50+ <> colourBoxes "Yellow" Palette.yellow
51+ <> colourBoxes "Mango" Palette.mango
5252 ]
5353
5454colourBoxes ∷ String -> ColourVariants -> Array JSX
@@ -58,14 +58,18 @@ colourBoxes name colours =
5858 , colourBox name (Proxy ∷ _ "dark") colours
5959 ]
6060
61−colourBox ∷
62− ∀ t13 t14 t15 colourVariant.
63− IsSymbol colourVariant =>
64− Cons colourVariant Color t15 t14 =>
65− String -> t13 colourVariant -> Record t14 -> JSX
61+colourBox
62+ ∷ ∀ t14 t15 colourVariant
63+ . IsSymbol colourVariant
64+ => Cons colourVariant Color t15 t14
65+ => String
66+ -> Proxy colourVariant
67+ -> Record t14
68+ -> JSX
6669colourBox name proxy colours =
6770 Box.component
68− </ { background: cssStringRGBA colour
71+ </
72+ { background: cssStringRGBA colour
6973 , css: E.css { color: E.str if isLight colour then "black" else "white" }
7074 , borderRadius: E.var "--s0"
7175 , boxShadow: E.str $ "0 1px 6px " <> Style.colour.boxShadow
src/Yoga/Prelude/View.purs+5−51
@@ -12,9 +12,11 @@ module Yoga.Prelude.View
1212 , module Web.HTML.HTMLElement
1313 , module Data.Nullable
1414 , module Untagged.Castable
15+ , module Web.DOM.Element
1516 ) where
1617
1718import Yoga.Prelude.Default hiding (div)
19+
1820import Data.Nullable (Nullable, notNull, null)
1921import Prim.Row (class Union)
2022import React.Basic.DOM (Props_div)
@@ -24,55 +26,7 @@ import React.Basic.Hooks (type (/\), Component, Hook, JSX, Pure, ReactChildren,
2426import Type.Row (type (+))
2527import Untagged.Castable (cast)
2628import Web.DOM (Node)
27−import Web.HTML.HTMLElement (HTMLElement, DOMRect, blur, focus, getBoundingClientRect)
29+import Web.DOM.Element (DOMRect, getBoundingClientRect)
30+import Web.HTML.HTMLElement (HTMLElement, blur, focus)
2831import Yoga ((/>), (</), (</*), (</*>), (</>), div, span, button)
29−import Yoga.Block.Internal
30− ( ButtonReadableProps
31− , ButtonReadablePropsF
32− , ButtonWritableProps
33− , ButtonWritablePropsF
34− , DivProps
35− , DivPropsF
36− , Id
37− , InputReadableProps
38− , InputReadablePropsF
39− , InputWritableProps
40− , InputWritablePropsF
41− , NodeRef
42− , OptionalProp(..)
43− , _0
44− , appendIfDefined
45− , asOptional
46− , composeHandler
47− , createRef
48− , dangerous
49− , emotionButton
50− , emotionDiv
51− , emotionInput
52− , forwardedRefAsMaybe
53− , getBoundingBoxFromRef
54− , getHTMLElementFromRef
55− , getOr
56− , getOrFlipped
57− , ifTrue
58− , isTruthy
59− , maybeToOp
60− , mkForwardRefComponent
61− , mkForwardRefComponentEffect
62− , opToMaybe
63− , setOrDelete
64− , unsafeDiv
65− , unsafeEmotion
66− , unsafeMergeSecond
67− , unsafeUnMaybe
68− , unsafeUnOptional
69− , unsafeUnionDroppingUndefined
70− , (<>?)
71− , (?||)
72− , getOffsetHeightFromRef
73− , getOffsetWidthFromRef
74− , getOffsetDimensionsFromRef
75− , getScrollHeightFromRef
76− , getScrollWidthFromRef
77− , getScrollDimensionsFromRef
78− )
32+import Yoga.Block.Internal (ButtonReadableProps, ButtonReadablePropsF, ButtonWritableProps, ButtonWritablePropsF, DivProps, DivPropsF, Id, InputReadableProps, InputReadablePropsF, InputWritableProps, InputWritablePropsF, NodeRef, OptionalProp(..), _0, appendIfDefined, asOptional, composeHandler, createRef, dangerous, deleteUndefineds, emotionButton, emotionDiv, emotionInput, forwardedRefAsMaybe, getBoundingBoxFromRef, getHTMLElementFromRef, getOffsetDimensionsFromRef, getOffsetHeightFromRef, getOffsetWidthFromRef, getOr, getOrFlipped, getScrollDimensionsFromRef, getScrollHeightFromRef, getScrollWidthFromRef, ifTrue, isTruthy, maybeToOp, mkForwardRefComponent, mkForwardRefComponentEffect, opToMaybe, setOrDelete, unsafeAddProps, unsafeDiv, unsafeEmotion, unsafeMergeSecond, unsafeUnMaybe, unsafeUnOptional, unsafeUnionDroppingUndefined, (<>?), (?||))