11module Lumi.Components.Form
2- ( module Internal
2+ ( module Defaults
3+ , module Internal
34 , module Validation
45 , build
5- , buildConcurrently
6- , buildWithDefaults
76 , static
87 , section
98 , inputBox
@@ -66,7 +65,8 @@ import JSS (JSS, jss)
6665import Lumi.Components.Color (colors )
6766import Lumi.Components.Column (column )
6867import Lumi.Components.FetchCache as FetchCache
69- import Lumi.Components.Form.Internal (FormBuilder (..), SeqFormBuilder , Tree (..), formBuilder , formBuilder_ , invalidate , revalidate , sequential , pruneTree )
68+ import Lumi.Components.Form.Defaults (formDefaults ) as Defaults
69+ import Lumi.Components.Form.Internal (FormBuilder (..), SeqFormBuilder , Tree (..), formBuilder , formBuilder_ , invalidate , pruneTree , sequential )
7070import Lumi.Components.Form.Internal (FormBuilder , SeqFormBuilder , formBuilder , formBuilder_ , invalidate , listen , parallel , revalidate , sequential ) as Internal
7171import Lumi.Components.Form.Validation (Validated (..), Validator , _Validated , fromValidated , mustBe , mustEqual , nonEmpty , nonEmptyArray , nonNull , validNumber , validInt , optional , setFresh , setModified , validated , warn ) as Validation
7272import Lumi.Components.Input (alignToInput )
@@ -89,7 +89,7 @@ import React.Basic.DOM (css, unsafeCreateDOMComponent)
8989import React.Basic.DOM as R
9090import React.Basic.DOM.Events (capture , stopPropagation , targetChecked , targetValue )
9191import React.Basic.Events as Events
92- import Record (disjointUnion , get )
92+ import Record (get )
9393import Type.Row (class Cons )
9494import Unsafe.Coerce (unsafeCoerce )
9595
@@ -98,30 +98,6 @@ import Unsafe.Coerce (unsafeCoerce)
9898-- | _Note_: this function should be fully applied, to avoid remounting
9999-- | the component on each render.
100100build
101- :: forall props unvalidated result
102- . FormBuilder { readonly :: Boolean | props } unvalidated result
103- -> { value :: unvalidated
104- , onChange :: Maybe result -> unvalidated -> Effect Unit
105- , inlineTable :: Boolean
106- , forceTopLabels :: Boolean
107- , readonly :: Boolean
108- | props
109- }
110- -> JSX
111- build editor = \props ->
112- form props
113- { onChange = \f ->
114- let v = f props.value
115- in props.onChange (revalidate editor (unsafeCoerce props) v) v
116- }
117- where
118- form = buildConcurrently editor
119-
120- -- | Create a React component for a form from a `FormBuilder`.
121- -- |
122- -- | _Note_: this function should be fully applied, to avoid remounting
123- -- | the component on each render.
124- buildConcurrently
125101 :: forall props unvalidated result
126102 . FormBuilder { readonly :: Boolean | props } unvalidated result
127103 -> { value :: unvalidated
@@ -132,7 +108,7 @@ buildConcurrently
132108 | props
133109 }
134110 -> JSX
135- buildConcurrently editor = makeStateless (createComponent " Form" ) render where
111+ build editor = makeStateless (createComponent " Form" ) render where
136112 render props@{ value, onChange, inlineTable, forceTopLabels, readonly } =
137113
138114 let forest = Array .mapMaybe pruneTree $ edit onChange
@@ -159,8 +135,10 @@ buildConcurrently editor = makeStateless (createComponent "Form") render where
159135 Child { key, child } ->
160136 maybe identity keyed key $ child
161137 Wrapper { key, children } ->
162- maybe identity keyed key $
163- fragment [ intercalate fieldDivider (map toRow children) ]
138+ R .div
139+ { key: fromMaybe " " key
140+ , children: [ intercalate fieldDivider (map toRow children) ]
141+ }
164142 Node { label, key, required, validationError, children } ->
165143 maybe identity keyed key $ labeledField
166144 { label: text body
@@ -182,29 +160,6 @@ buildConcurrently editor = makeStateless (createComponent "Form") render where
182160 , children: surround fieldDivider (map toRow forest)
183161 }
184162
185- -- | Utility function.
186- -- | Create a React component for a form from a `FormBuilder` and a default
187- -- | form state. This default value is used in the form whenever the `value`
188- -- | prop is `Nothing`.
189- -- |
190- -- | _Note_: this function should be fully applied, to avoid remounting
191- -- | the component on each render.
192- buildWithDefaults
193- :: forall props unvalidated result
194- . unvalidated
195- -> FormBuilder { readonly :: Boolean | props } unvalidated result
196- -> { value :: Maybe unvalidated
197- , onChange :: Maybe result -> unvalidated -> Effect Unit
198- , inlineTable :: Boolean
199- , forceTopLabels :: Boolean
200- , readonly :: Boolean
201- | props
202- }
203- -> JSX
204- buildWithDefaults defaults editor = \props -> form props { value = fromMaybe defaults props.value }
205- where
206- form = build editor
207-
208163-- | Create an always-valid `FormBuilder` that renders the supplied `JSX`.
209164static :: forall props value . JSX -> FormBuilder props value Unit
210165static edit = formBuilder \_ _ -> { edit: const edit, validate: pure unit }
@@ -786,17 +741,20 @@ fetch_ loading getData = fetch loading "" (const getData)
786741-- | A dummy form that, whenever the specified key changes, performs an
787742-- | asynchronous effect. It displays the specified JSX while the effect is not
788743-- | complete, sets the form data to the result of the effect and returns it.
789- asyncEffect :: forall props a . String -> JSX -> Aff a -> FormBuilder props a a
744+ asyncEffect :: forall props a . String -> JSX -> Aff ( a -> a ) -> FormBuilder props a a
790745asyncEffect key loader aff =
791- withKey key $ formBuilder_ \_ _ onChange ->
792- keyed key $ asyncWithLoader loader do
793- newValue <- aff
794- liftEffect $ onChange newValue
795- mempty
746+ withKey key $ formBuilder \_ value ->
747+ { edit: \onChange ->
748+ keyed key $ asyncWithLoader loader do
749+ f <- aff
750+ liftEffect $ onChange f
751+ mempty
752+ , validate: Just value
753+ }
796754
797755-- | A dummy form that, whenever the specified key changes, performs an
798756-- | effect. It sets the form data to the result of the effect and returns it.
799- effect :: forall props a . String -> Effect a -> FormBuilder props a a
757+ effect :: forall props a . String -> Effect ( a -> a ) -> FormBuilder props a a
800758effect key = asyncEffect key mempty <<< liftEffect
801759
802760-- | Sequential `SeqFormBuilder` used for asynchronously initializing some
@@ -823,16 +781,18 @@ initializer
823781 :: forall props value
824782 . Nub (initialized :: Boolean | value ) (initialized :: Boolean | value )
825783 => JSX
826- -> (props -> { | value } -> Aff { | value } )
784+ -> (props -> { | value } -> Aff ( { initialized :: Boolean | value } -> { initialized :: Boolean | value } ) )
827785 -> SeqFormBuilder props { initialized :: Boolean | value } Unit
828786initializer loader aff =
829787 sequential " initializer" $ withValue \value@{ initialized } -> withProps \props ->
830- if initialized
831- then pure unit
832- else
833- invalidate $ void $ asyncEffect " " loader do
834- newValue <- aff props (contractValue value)
835- pure $ disjointUnion { initialized: true } newValue
788+ if initialized then
789+ pure unit
790+ else
791+ invalidate
792+ $ void
793+ $ asyncEffect " " loader
794+ $ map (_{ initialized = true } <<< _)
795+ $ aff props (contractValue value)
836796 where
837797 contractValue :: { initialized :: Boolean | value } -> { | value }
838798 contractValue = unsafeCoerce
0 commit comments