Last active
May 17, 2024 15:12
-
-
Save lukaszkrzywizna/917d8f994082bab595d949bbd4dd3dc5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[<Erase>] | |
type IProp<'comp when 'comp : not struct> = | Prop of string * obj | |
with | |
static member inline Create (value: string * obj) = Prop value | |
static member inline Build(props: IProp<'comp> seq) = props |> unbox<(string * obj) seq> |> createObj |> unbox<'comp> | |
let inline (!<) x = IProp.Build x | |
module Interop = | |
let inline mkProperty<'Component when 'Component : not struct> (key:string) (value:obj) : IProp<'Component> = | |
IProp.Create (key, value) | |
// Interfaces with attributes has two sections: | |
// 1) abstract member used for prop access withing the component | |
// 2) static member inline functions - used for prop creation (later transformed into an object with IProp.Build) | |
[<Interface>] | |
type AriaAttributes = | |
abstract member ``aria-activedescendant`` : string option with get | |
static member inline AriaActiveDescendant (id: string) = | |
Interop.mkProperty<#AriaAttributes> (nameof(Unchecked.defaultof<AriaAttributes>.``aria-activedescendant``)) id | |
abstract member ``aria-atomic`` : bool option with get | |
static member inline AriaAtomic (value: bool) = | |
Interop.mkProperty<#AriaAttributes> (nameof(Unchecked.defaultof<AriaAttributes>.``aria-atomic``)) value | |
// and more... | |
[<Interface>] | |
type DOMAttributes<'element & #Element & #EventTarget> = | |
abstract member onCopy : ClipboardEventHandler<'element> option with get | |
static member inline OnCopy (value: ClipboardEventHandler<'element>) = | |
Interop.mkProperty<#DOMAttributes<'element>> (nameof(Unchecked.defaultof<DOMAttributes<'element>>.onCopy)) value | |
// and more... | |
[<Interface>] | |
type HTMLAttributes<'element & #Element & #EventTarget> = | |
inherit AriaAttributes | |
inherit DOMAttributes<'element> | |
// React-specific Attributes | |
abstract member defaultChecked: bool option with get | |
static member inline DefaultChecked (value: bool) = | |
Interop.mkProperty<#HTMLAttributes<'element>> (nameof(Unchecked.defaultof<HTMLAttributes<'element>>.defaultChecked)) value | |
// and more... | |
[<Interface>] | |
type InputHTMLAttributes<'element & #Element & #EventTarget> = | |
inherit HTMLAttributes<'element> | |
abstract member disabled: bool option with get | |
static member inline Disabled (value: bool) = | |
Interop.mkProperty<#InputHTMLAttributes<'element>> (nameof(Unchecked.defaultof<InputHTMLAttributes<'element>>.disabled)) value | |
[<Interface>] | |
type input = | |
inherit InputHTMLAttributes<HTMLInputElement> | |
[<Erase>] | |
type Html = | |
static member inline input (props: input) = Interop.reactElement "input" props | |
static member inline input (xs: IProp<input> list) = Html.input !< xs | |
/// We can build the input element using props from all inherited interfaces. | |
Html.input [ | |
input.DefaultChecked true | |
input.Disabled false // only available for input type | |
input.OnCopy(fun (e: ClipboardEventHandler<HTMLInputElement>) -> ignore e) // note the event type | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment