Feliz: рд╡реИрдХрд▓реНрдкрд┐рдХ рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рд╡рд╛рдХреНрдп рд░рдЪрдирд╛

рдХреЛ рдирд┐рд░реНрдорд┐рдд 9 рдЕрдХреНрддреВре░ 2019  ┬╖  13рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: Zaid-Ajaj/Feliz

рдЖрдк рдЗрд╕ рддрд░рд╣ рдХреЗ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕рд╛ рдорд╣рд╕реВрд╕ рдХрд░рддреЗ рд╣реИрдВ? (рдореИрдВрдиреЗ рдЗрд╕реЗ рдЬрд▓реНрджреА рд╕реЗ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рд╣реИ; рд╕реБрдзрд╛рд░ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЬрдЧрд╣ рд╣реЛ рд╕рдХрддреА рд╣реИ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдХ рдХреЗ рдЕрдВрдд рдореЗрдВ .reactElement рдХреЛ рдЦрддреНрдо рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм рдЗрд╕ рдкрд░ рдЕрдзрд┐рдХ рд╕рд╛рд╡рдзрд╛рдиреА рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред)

``` рдЪ#
рдРрдкрдмрд╛рд░ ()
.рд╕реНрдерд┐рддрд┐.рдирд┐рд░рдкреЗрдХреНрд╖
редрдмрдЪреНрдЪреЗ([
рдЯрд╛рдЗрдкреЛрдЧреНрд░рд╛рдлреА ()
.variant.h6
.рд░рдВрдЧ.рдкреНрд░рд╛рдердорд┐рдХ
.рдкрд╛рда ("рдлреВ")
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рддрддреНрд╡
])
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рддрддреНрд╡

Benefits: Supports inheritance, and puts a final end to any discoverability issues still left in Feliz: No more hunting for the correct prop type; you're just dotting through and seeing what's available. Also supports overloaded props and enum props just like Feliz; we have basically just replaced property lists with "fluent builders".

Drawbacks: I don't know which impacts this has for bundle size or performance (see quick and dirty implementation below). Also it's "unusual" as far as Fable goes (no prop lists). Not that the latter matters by itself. **Update:** See more challenges here: https://github.com/Zaid-Ajaj/Feliz/issues/54#issuecomment-541658081

I'm not saying we should necessarily do this; I just wanted to get this out of my head and post it for discussion.

For the record, below is the implementation of the above syntax. I have not made any attempts to inline or erase stuff. And there's a bit of type trickery which would likely cause OO fanatics to spin in their graves (what with subtypes inheriting base types parametrized by the subtype and all).

```f#
open Fable.Core.JsInterop
open Fable.React

let reactElement (el: ReactElementType) (props: 'a) : ReactElement =
  import "createElement" "react"


[<AbstractClass>]
type PropsBase() =
  abstract ElementType : ReactElementType
  member internal __.Props = ResizeArray<string * obj>()
  member internal this.reactElement =
    reactElement this.ElementType (createObj this.Props)


[<AbstractClass>]
type PropsBase<'a>() =
  inherit PropsBase()

  member this.custom (key: string) (value: obj) =
    this.Props.Add(key, value)
    this |> unbox<'a>

  member this.children (elems: seq<ReactElement>) =
    // should also call React.Children.ToArray
    this.custom "children" elems

  member this.text (text: string) =
    this.custom "children" text


type AppBarPosition<'a when 'a :> PropsBase<'a>>(parent: 'a) =
  member __.absolute = parent.custom "position" "absolute"
  member __.relative = parent.custom "position" "relative"


type AppBar() =
  inherit PropsBase<AppBar> ()
  member this.position = AppBarPosition(this)
  override __.ElementType = importDefault "@material-ui/core/AppBar"


type TypographyVariant<'a when 'a :> PropsBase<'a>>(parent: 'a) =
  member __.h5 = parent.custom "variant" "h5"
  member __.h6 = parent.custom "variant" "h6"

type TypographyColor<'a when 'a :> PropsBase<'a>>(parent: 'a) =
  member __.primary = parent.custom "color" "primary"
  member __.secondary = parent.custom "color" "secondary"


type Typography() =
  inherit PropsBase<Typography> ()
  member this.variant = TypographyVariant(this)
  member this.color = TypographyColor(this)
  override __.ElementType = importDefault "@material-ui/core/Typography"

рд╕рднреА 13 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдпрджрд┐ .reactElement рдЪрд▓рд╛ рдЬрд╛рдПрдЧрд╛, рддреЛ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ OK-ish рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрдиреНрдп рддреГрддреАрдп-рдкрдХреНрд╖ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рдкрд░ рдпрд╣ рдЕрд▓рдЧ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрдо рд╕реЗ рдХрдо рдЗрд╕рдХреЗ рд╕рд╛рде рд░рд╣ рд╕рдХрддреЗ рд╣реИрдВ:

Html.div [
  Mui.appBar()
    .position.absolute
    .children([
      Mui.typography()
        .variant.h6
        .color.primary
        .text("Foo")
    ])
]

рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЕрднреА рднреА рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдзрд╛рд░ рдЧреБрдгреЛрдВ рдХреА рдирдХрд▓ рдХрд░рдирд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ред рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдЖрдкрдХреЛ рд╣рд░ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХреА рдирдХрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдХрдИ рдмрд╛рд░ рдЖрдк рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рдмрд╕ рдЙрди рд▓реЛрдЧреЛрдВ рдХреА рдирдХрд▓ рдХрд░реЗрдВ рдЬрд┐рдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рдХреА рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ: id , key , className , style , children рдФрд░ рдмрд╣реБрдд рд╣реА рджреБрд░реНрд▓рдн рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП prop рд╡рд╛рдкрд╕ рдЧрд┐рд░рдирд╛ред рддреБрдо рдХреНрдпрд╛ рд╕реЛрдЪрддреЗ рд╣реЛ?

https://github.com/cmeeren/Feliz.MaterialUI/issues/20 рдореЗрдВ рд╡рдВрд╢рд╛рдиреБрдХреНрд░рдо рдХреА рдирд┐рд░рдВрддрд░ рдЪрд░реНрдЪрд╛ рдЪреВрдВрдХрд┐ рдпрд╣ рдореБрджреНрджрд╛ рдХреЗрд╡рд▓ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИ, рдЬреЛ рдХрд┐ рд╡рд┐рд░рд╛рд╕рдд рдХреЗ рд╕рд╛рде рдореЗрд░реЗ рд╕рдВрдШрд░реНрд╖реЛрдВ рд╕реЗ рдЕрд▓рдЧ рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдПрдХ рд╡рд┐рдЪрд╛рд░ рд╣реИ (рдХреНрд╖рдорд╛ рдХрд░реЗрдВ рдпрджрд┐ рд╡рд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рдерд╛)ред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдореЗрдВ рдПрдХ рдФрд░ рдХрдореА рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдпрджрд┐ рдореИрдВ рдПрдХ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рдирд┐рдпрдВрддреНрд░рдг рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рддреЛ рдореИрдВ рдЙрдкрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ! рдирдП рд╕рд╣рд╛рд░рд╛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдПред рдпрд╛ рдореИрдВ рд╕реАрдорд┐рдд рдкреНрд░реЙрдкреНрд╕ рдХреЗ рд▓рд┐рдП рдпреВрдирд┐рдпрди рдХреЗрд╕ рдмрдирд╛ рд╕рдХрддрд╛ рд╣реВрдВ рдФрд░ рдмреЗрд╕ рдкреНрд░реЙрдкреНрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдо рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рдФрд░ рдЗрд╕реЗ рдХрд╣реАрдВ рднреА рдореИрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рд▓реЗрдХрд┐рди рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рд╡рд╛рдХреНрдп рд░рдЪрдирд╛ рдХреЗ рд╕рд╛рде рдореИрдВ рдХреЗрд╡рд▓ рдЕрдВрдд рдореЗрдВ рд╕рд╣рд╛рд░рд╛ рдЬреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реВрдБред

let myButton props =
    Html.button [
        prop.Classes [ ... ]
        prop.Style [....]
        yield! props
    ]

@albertwoo рдореБрдЭреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЖрдкрдХрд╛ рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИ

рдпрд╛ рдореИрдВ рд╕реАрдорд┐рдд рдкреНрд░реЙрдкреНрд╕ рдХреЗ рд▓рд┐рдП рдпреВрдирд┐рдпрди рдХреЗрд╕ рдмрдирд╛ рд╕рдХрддрд╛ рд╣реВрдВ рдФрд░ рдмреЗрд╕ рдкреНрд░реЙрдкреНрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдо рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рдФрд░ рдЗрд╕реЗ рдХрд╣реАрдВ рднреА рдореИрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рд▓реЗрдХрд┐рди рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдкреНрд░реЙрдкреНрд╕ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рдиреЗ рдореЗрдВ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ:

f# let myButton props = Html.button .classes([...]) .style([...]) .custom(props)

рдЬрд╣рд╛рдВ custom рд╣рдо рдЬреЛ рдХреБрдЫ рднреА рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЙрд╕реЗ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдУрд╡рд░рд▓реЛрдб рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ:

  • string * obj
  • рдлрд╝реЗрд▓рд┐рдЬрд╝ рдкреНрд░реЛрдк рдкреНрд░рдХрд╛рд░ (рдЗрдВрдЯрд░рдСрдк рдХреЗ рд▓рд┐рдП)
  • Fable.React рдкреНрд░реЛрдк рдкреНрд░рдХрд╛рд░ (рдЗрдВрдЯрд░рдСрдк рдХреЗ рд▓рд┐рдП)
  • рдЙрдкрд░реЛрдХреНрдд рдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдХреЗ рдЕрдиреБрдХреНрд░рдо

рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╡рд╛рд▓реЗ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рдШрдЯрдХреЛрдВ рдХреЗ рд▓рд┐рдП, рдЖрдк рд╢рд╛рдпрдж рдЙрд╕ рддрд░рд╣ рдХреЗ рдкреНрд░реЛрдк рдкрд╛рд╕ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рдЖрдк рдХреБрдЫ рдРрд╕рд╛ рдХрд░реЗрдВрдЧреЗ:

``` рдЪ#
рдЪрд▓реЛ myButton () =
рдПрдЪрдЯреАрдПрдордПрд▓.рдмрдЯрди
рдХрдХреНрд╖рд╛рдПрдВ ([...])
редрдЕрдВрджрд╛рдЬ([...])

And then use it like this:

```f#
myButton()
  .text("foo")

рдореБрдЭреЗ рдкреНрд░реЙрдкреНрд╕ рд▓рд┐рд╕реНрдЯ рд╕реНрдЯрд╛рдЗрд▓ рдкрд╕рдВрдж рд╣реИред рдореЗрд░реЗ рдХреЛрдб рдореЗрдВ рдореИрдВрдиреЗ рдХреБрдЫ рдРрд╕рд╛ рдХрд┐рдпрд╛:

type ISimpleFieldProp = interface end

[<RequireQualifiedAccess>]
type SimpleFieldProp =
  | Label of string
  | Errors of string list 
  | OuterClasses of string list
  | LabelClasses of string list
  | ErrorClasses of string list
  | FieldView of ReactElement
  | OuterAttrs of IHTMLProp list
  interface ISimpleFieldProp

let simpleField (props: ISimpleFieldProp list) =
    let props = props |> List.choose (function :? SimpleFieldProp as x -> Some x | _ -> None)
    let label             = props |> UnionProps.tryLast (function SimpleFieldProp.Label x -> Some x | _ -> None)
    let errorClasses      = props |> UnionProps.tryLast (function SimpleFieldProp.ErrorClasses x -> Some x | _ -> None) |> Option.defaultValue []
    let outerClasses      = props |> UnionProps.concat (function SimpleFieldProp.OuterClasses x -> Some x | _ -> None)
    let labelClasses      = props |> UnionProps.concat (function SimpleFieldProp.LabelClasses x -> Some x | _ -> None)

    div </> [
      yield! props |> UnionProps.concat (function SimpleFieldProp.OuterAttrs x -> Some x | _ -> None)
      match outerClasses with
        | [] -> Style [ Margin "5px"; Padding "5px" ]
        | cs -> Classes cs
      Children [
        if label.IsSome then fieldLabel labelClasses label.Value 

        match props > UnionProps.tryLast (function SimpleFieldProp.FieldView x -> Some x | _ -> None) with
          | Some x -> x
          | None    -> ()

        yield! 
          props 
          |> UnionProps.concat (function SimpleFieldProp.Errors x -> Some x | _ -> None)
          |> fieldError errorClasses
      ]
    ]

UnionProps.concat рдореИрдВ IHTMLProp, рдХреНрд▓рд╛рд╕ рд╕реНрдЯреНрд░рд┐рдВрдЧ, рд╕реНрдЯрд╛рдЗрд▓ рдЖрджрд┐ рдЬреИрд╕реА рд╕рднреА рдЪреАрдЬреЛрдВ рдХреЛ рдорд░реНрдЬ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рдФрд░ Fable.React рдХреЛ рдлреАрдб рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред рддрдм рдореИрдВ рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ:

let simpleField1 props =
   simpleField [
      SimpleFieldProp.OuterClasses [ ... ]
   ]
let simpleField2 props =
   simpleField1 [
      SimpleFieldProp.OuterClasses [ ... ]
   ]

рдФрд░ рд╕рднреА OuterClasses рдПрдХ рд╕рд╛рде рд╡рд┐рд▓реАрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдмреЗрд╢рдХ рдЕрдЧрд░ рдПрдХ рд╕рд╛рде рд╡рд┐рд▓рдп рдирд╣реАрдВ рд╣реИ рддреЛ рдореИрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдореИрдВ рд╕рд┐рд░реНрдл UnionProps.tryLast рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХреВрдВред

рд╡рд┐рд╕реНрддреГрдд рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдореБрдЭреЗ рдпрд╣ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдЗрд╕рдиреЗ рдореБрдЭреЗ рднреНрд░рдорд┐рдд рдХрд░ рджрд┐рдпрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдлрд╝реЗрд▓рд┐рдЬрд╝ рдХрд╛ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕рд╛рдорд╛рдиреНрдп Fable.Reactред рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдпрд╣ рд╕рдордЭрдиреЗ рдореЗрдВ рдореБрд╢реНрдХрд┐рд▓ рд╣реЛ рд░рд╣реА рд╣реИ рдХрд┐ рдпрд╣ рдЗрд╕ рдЪрд░реНрдЪрд╛ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИред

рд╕рд╛рде рд╣реА, рдХрдИ "рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓реА"/рд░рдЪрд┐рдд рдХрдХреНрд╖рд╛рдУрдВ рд╕реЗ рдПрдХ рд╣реА рдкреНрд░реЛрдк рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрдк рдорд╛рдиреЛрдВ рдХреЛ рд╡рд┐рд▓рдп рдХрд░рдирд╛ рдореБрдЭреЗ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд┐рд▓рд┐рдЯреА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рдЧрдиреНрджрд╛ рддрд░реАрдХрд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд░рд┐рдПрдХреНрдЯ/рдЬреЗрдПрд╕рдПрдХреНрд╕ рдЖрдзрд╛рд░рд┐рдд рд╕рд┐рдВрдЯреИрдХреНрд╕ (рдПрдПрдлрдПрдЖрдИрдХреЗ) рдореЗрдВ рдПрдХ рдШрдЯрдХ рдореЗрдВ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рдкреНрд░реЛрдк рдХреА рдХреЗрд╡рд▓ рдПрдХ рдШрдЯрдирд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ .

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЬреЛ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╡рд╣ рдПрдХ рдХрд╕реНрдЯрдо рдШрдЯрдХ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рд╣реИ рдЬреЛ рдореБрдЯреНрдареА рднрд░ рд╡реИрдХрд▓реНрдкрд┐рдХ, рдХрд╕реНрдЯрдо рдкреНрд░реЙрдкреНрд╕ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдкреНрд░реЙрдкреНрд╕ рд╣реИрдВ рдФрд░ рдЬрд┐рдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдЪрд╛рдЗрд▓реНрдб рдПрд▓рд┐рдореЗрдВрдЯ рд╣реИрдВред

рдлрд╝реЗрд▓рд┐рдЬрд╝ рдореЗрдВ (рдЬреИрд╕рд╛ рдХрд┐ рдЕрдм рд╣реИ, рдмрд┐рдирд╛ рдХрд┐рд╕реА рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ), рдореЗрд░реЗ рд╕рд┐рд░ рдХреЗ рдКрдкрд░ рд╕реЗ, рдореИрдВ рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд╣рд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ (рдЖрдВрд╢рд┐рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди; рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдмрд╛рдХреА рдкреНрд░реЛрдк рд╕реНрдкрд╖реНрдЯ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП):

``` рдЪ#
рдлрд╝реЗрд▓рд┐рдЬрд╝реЛ рдЦреЛрд▓реЗрдВ

рдХреЗ рд╕рд╛рде рдПрдЪрдЯреАрдПрдордПрд▓ рдЯрд╛рдЗрдк рдХрд░реЗрдВ

рд╕рджрд╕реНрдп рд╕рд░рд▓ рдлрд╝реАрд▓реНрдб (
рд▓реЗрдмрд▓: рд╕реНрдЯреНрд░рд┐рдВрдЧ,
рддреНрд░реБрдЯрд┐рдпрд╛рдБ: рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реВрдЪреА,
рд▓реЗрдмрд▓ рдХреНрд▓рд╛рд╕реЗрд╕: рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реВрдЪреА,
?outerClasses: рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реВрдЪреА
рдкреНрд░реЙрдкреНрд╕: IReactProperty рд╕реВрдЪреА) =
// рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рд╕рд╣реА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ UnionProps.concat рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрдпрд╛ рд╣реИ
// рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрдХреАрди рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдЬрд┐рд╕реНрдЯ рдорд┐рд▓ рдЧрдпрд╛ рд╣реИ
рдЪрд▓реЛ lbClasses = labelClasses |> Option.defaultValue []

Html.div [
  yield! props |> Option.defaultValue []
  outerClasses |> Option.map prop.classes |> Option.defaultValue (prop.style [ ... ])
  prop.children [
    match label with Some lb -> fieldLabel lbClasses lb | None -> ()
    ...
  ]
]
This also allows you to easily make any of the props required, if you desire.

As regards the fluent syntax under discussion, it would work the same way.

The usage of the example above would be:

```f#
Html.simpleField(
  label = "foo",
  outerClasses = ["bar"]
)

рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХрд╕реНрдЯрдо рд░рд┐рдПрдХреНрдЯ рдШрдЯрдХ рдмрдирд╛рдирд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП Fable.React рдХреЗ FunctionComponent.Of рд╕рд╛рде рдлрд╝рдВрдХреНрд╢рди рдШрдЯрдХ) рдкреБрди: рдкреНрд░рдпреЛрдЬреНрдп рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╢рд╛рдирджрд╛рд░ рддрд░реАрдХрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рд╣рд╛рдВ, рдореИрдВ рдлреЗрд▓рд┐рдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ (рдореИрдВрдиреЗ рдХреЛрд╢рд┐рд╢ рдХреА рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рдХреЛрдИ рдПрд╕рдПрд╕рдЖрд░ рд╕рдорд░реНрдерди рдирд╣реАрдВ рд╣реИ)ред рд▓реЗрдХрд┐рди рдореИрдВ рд╕рд┐рд░реНрдл рдкреНрд░реЛрдк рд▓рд┐рд╕реНрдЯ рд╕реНрдЯрд╛рдЗрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдкрдиреЗ рд╡рд┐рдЪрд╛рд░ рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рд╣рд╛рдВ рдХреНрд▓рд╛рд╕ рдФрд░ рд╕реНрдЯрд╛рдЗрд▓ рдЬреИрд╕реЗ рдкреНрд░реЙрдкреНрд╕ рдХреЛ рдПрдХ рд╕рд╛рде рдорд┐рд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдЧрдбрд╝рдмрдбрд╝ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдЕрдкрдирд╛ рдРрдк рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЪреАрдЬреЛрдВ рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛ рджреЗрддрд╛ рд╣реИред
рдЖрдкрдХрд╛ рдЙрдкрд░реЛрдХреНрдд рдЙрджрд╛рд╣рд░рдг рд╢рд╛рдирджрд╛рд░ рдЬрд╝рд╛рдорд░реАрди рдбрд┐рдлрд╝реЙрд▓реНрдЯ рддрд░реАрдХреЗ рд╕реЗ рдмрд╣реБрдд рдкрд╕рдВрдж рд╣реИ (рдореИрдВ рдЙрд╕ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ)ред рдХрднреА-рдХрднреА simpleField рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдпрджрд┐ рдореИрдВ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП simpleField2 рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рддреЛ рдореБрдЭреЗ рдЗрдирдкреБрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рджреЛрд╣рд░рд╛рдирд╛ рд╣реЛрдЧрд╛ рдЬреИрд╕реЗ:

type Html with
   member simpleField2(
      ?label: string,
      ?errors: string list,
      ?labelClasses: string list,
      ?outerClasses: string list
      ?props: IReactProperty list) =
     simpleField(label, errors, labelClasses, [ "bar"; yield! outerClasses ], props)

рдЖрдк рд▓реЛрдЧ рдХрд╛рдо рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХрд░рддреЗ рд╣реИрдВ !!!

:)

рд╕рдВрднрд╛рд╡рд┐рдд рдЙрдкрд╛рдп:

``` рдЪ#
SimpleFieldProps рдЯрд╛рдЗрдк рдХрд░реЗрдВ = {
рд▓реЗрдмрд▓: рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╡рд┐рдХрд▓реНрдк
рддреНрд░реБрдЯрд┐рдпрд╛рдБ: рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реВрдЪреА
//...
} рд╕рд╛рде
рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдп рдмрдирд╛рдПрдБ (? рд▓реЗрдмрд▓: рд╕реНрдЯреНрд░рд┐рдВрдЧ,? рддреНрд░реБрдЯрд┐рдпрд╛рдБ: рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реВрдЪреА, ..) = {..}

рдХреЗ рд╕рд╛рде рдПрдЪрдЯреАрдПрдордПрд▓ рдЯрд╛рдЗрдк рдХрд░реЗрдВ
рд╕рджрд╕реНрдп рд╕рд┐рдВрдкрд▓рдлрд┐рд▓реНрдб (рдкреНрд░реЙрдкреНрд╕: рд╕рд┐рдВрдкрд▓рдлрд┐рд▓реНрд▓реНрдбрдкреНрд░реЙрдкреНрд╕) = // ...
рд╕рджрд╕реНрдп simpleField2 (рдкреНрд░реЙрдкреНрд╕: SimpleFieldProps) =//...

Usage:

```f#
Html.simpleField (SimpleFieldProps.create(..))

:) рд╕рд▓рд╛рд╣ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдЗрд╕ рддрд░рд╣ рд╕реЗ рдорджрдж рдорд┐рд▓ рд╕рдХрддреА рд╣реИ рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдореЗрд░реЗ рдкрд╛рд╕ рдлреИрдмреБрд▓рд╕ рдЬрд╝рд╛рдорд░реАрди рдЬреИрд╕реЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдкреНрд░реЙрдкреНрд╕ рд╣реИрдВ, рддреЛ рдпрд╣ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдХрд╛рдо рд╣реЛрдЧрд╛ред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдореИрдВ рднреА Fabulous.SimpleElements рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ (рдзрдиреНрдпрд╡рд╛рдж @ Zaid-Ajaj рдлрд┐рд░ рд╕реЗ :))

.reactElement рд╕рдВрдмрдВрдз рдореЗрдВ: AFAIK рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдореМрдЬреВрджрд╛ рдХреЛрдб рдХреЗ рд╕рд╛рде рдЗрдВрдЯрд░рдСрдкрд┐рдВрдЧ рдХрд░рддреЗ рд╕рдордп рдХреЗрд╡рд▓ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП reactElement рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЕрдиреНрдпрдерд╛, рдЧреБрдг рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ ReactElement рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рдПрдкреАрдЖрдИ рдореЗрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП children ) рднреА рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рднрд╛рд░ рдХреЗ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ PropsBase , рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рдмреБрд▓рд╛ .reactElement ред

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдХрдореА рдпрд╣ рд╣реИ рдХрд┐ рдЪреВрдВрдХрд┐ рд╕реВрдЪрд┐рдпреЛрдВ рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рд╕реВрдЪреА рдХреЗ рдЕрдВрджрд░ рдХреЛрдИ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдЕрдкрдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдирд╣реАрдВ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдЕрдкрдХрд╛рд╕реНрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП PropsBase ) рд╡реИрд╕реЗ рднреА рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рддрддреНрд╡ рд╣реИрдВред рдЬрдм рддрдХ рдЗрд╕рдХрд╛ рдХреЛрдИ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рди рд╣реЛ, рд╣рдо reactElement рднреА рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдЙрдкрд░реЛрдХреНрдд рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди рдмрд╛рд▓ рддрддреНрд╡реЛрдВ рдХреА рд╕реВрдЪреА рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди [<ParamArray>] рдХрд╛ PropsBase ред рддрдм рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреИрд░рд╛рдореАрдЯрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛ рдЬрд╛рдПрдВрдЧреЗред рд▓реЗрдХрд┐рди рдлрд┐рд░ рдЖрдкрдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдЖрдЗрдЯрдо рдХреЗ рдмреАрдЪ рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред (рдЖрдк [] рдХреЛ () рднреА рдмрджрд▓ рджреЗрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕рдХреА рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рд╣реИред)

рд╕рд╢рд░реНрдд рд╕рд╣рд╛рд░рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдкреАрдЖрдИ рднреА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╡рд░реНрддрдорд╛рди рдлрд╝реЗрд▓рд┐рдЬрд╝ (рдФрд░ Fable.React) DSL рдореЗрдВ рд╣рдо рдЪреБрдирд┐рдВрджрд╛ yield рдкреНрд░реЙрдкреНрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдЬрдВрдЬреАрд░ рдкреНрд░реЛрдк рдХреЙрд▓ рдХреЗ рд╕рд╛рде, рдпрд╣ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред рдпрд╣ рдПрдкреАрдЖрдИ рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд╛ рдорд╛рдорд▓рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рд╕реБрдВрджрд░ рд╣реЛрдЧрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдПрдирдо рдкреНрд░реЛрдк рдХреЗ рд▓рд┐рдП рдЬрд╣рд╛рдВ рдХреЛрдИ рдкреИрд░рд╛рдореАрдЯрд░ рдирд╣реАрдВ рд╣реИ - рддреЛ рд╣рдо bool рдкреИрд░рд╛рдореАрдЯрд░ рдирд╣реАрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдПрдХ рд╕рдорд╛рдзрд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдПред

рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд░реИрдкрд┐рдВрдЧ .conditional(bool, 'builder -> 'ignored) , рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП

f# .prop1("foo") .conditional(false, fun p -> p.prop2("bar")) .prop3("baz")

рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдмрд╕реЗ рд╕реБрдВрджрд░ рдПрдкреАрдЖрдИ рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рджреЗрдЦрд╛ рд╣реИред (рдмрд╣реБрдд рдмреБрд░рд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореМрдЬреВрджрд╛ рд╕рд╢рд░реНрдд yield рдмреЗрд╣рддрд░ IMHO рд╣реИред)

рдЕрдЧрд░ рдореИрдВ рд╕реА # рдореЗрдВ рдбреАрдПрд╕рдПрд▓ рд▓рд┐рдЦ рд░рд╣рд╛ рдерд╛, рддреЛ рдпрд╣ рд╡рд╣ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдл # рд╣реИ рдФрд░ рдпрд╣ рд╕рднреА рдЕрдЪреНрдЫреА рд╕реВрдЪреА рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рд╡рд░реНрддрдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ

рдЧреЛрдЪрд╛ред рдЗрд╕ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореБрдЭреЗ рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдкрд╕рдВрдж рд╣реИ рдХрд┐ рдпрд╣ рдЕрдм рддрдХ рдореИрдВрдиреЗ рджреЗрдЦрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЦреЛрдЬ рдпреЛрдЧреНрдп рд╣реИред рдЕрдиреНрдпрдерд╛ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╡рд░реНрддрдорд╛рди рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЗрд╕рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдХрдорд┐рдпрд╛рдВ рд╣реИрдВред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

theimowski picture theimowski  ┬╖  13рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

nojaf picture nojaf  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Dzoukr picture Dzoukr  ┬╖  10рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

cmeeren picture cmeeren  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Dzoukr picture Dzoukr  ┬╖  9рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ