Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class Based API vnext #40

Open
AngelMunoz opened this issue May 29, 2022 · 1 comment
Open

Class Based API vnext #40

AngelMunoz opened this issue May 29, 2022 · 1 comment

Comments

@AngelMunoz
Copy link
Collaborator

Taking advantage of the reactive controllers branch and it's very likely major version bump I also wanted to follow up #36 where it would be nice to expose the class based API to have better bind parity to lit.dev and also to allow newer users who may come from JS themselvs (or even other backgrounds) to be easier to just follow lit's docs and be able to do it on F# as well.

One of the big issues is that we can't emit typescript-like decorators yet and we shouldn't because the HTML spec differs from typescript's implementation (I'm not sure up to what detail but I know it does)

that being said I'm working on a computation expression which kind of matches the customElement decorator from typescript
we still need to track property definition vs properties inside the class but in my mind it should not be too much of a hassle because it's the same behavior lit.dev has in JavaScript

The proposed API would look like this

// classic class component definition for lit components
type UserProfile() =
    inherit LitElement()
    // manual declaration of internal properties
    let mutable name = ""
    let mutable age = 0

    override _.render() =
        html $"<p>{name} - {age}</p>"

// this auto registers the element using the same
// behavior as the decorator would do
registerElement "user-profile" jsConstructor<UserProfile> {
    property "name" {
        use_attribute
        use_type StringCtor
    }
    property "age" {
        use_attribute
        use_type JS.Constructors.Number
    }
}

It's usage would be as usual

<user-profile name="Peter" age="25"></user-profile

What it brings to the table is the ability to build the properties in a kind of type safe way with some auto-completition vs building the properties manually and try to remember each possibility

{| name = {| ``type`` = StringCtor; attribute = true |}
   age = {| ``type`` = JS.Constructors.Number; attribute = true |} |}

For cases where one may want to provide a component library for other F# users I also thought to have a way to let users cherry pick their own elements

[<AutoOpen>]
module ElementDefinitions = 
  let userProfileDef =
    delayedElement "user-profile" jsConstructor<UserProfile> {
      property "name" {
        use_attribute
        use_type StringCtor
      }
      property "age" {
        use_attribute
        use_type JS.Constructors.Number
      }
    } // ElementDefinition rather than auto registration

// let the user choose what they want to actually use
module CherryPick = 
  let userProfile() =
    // defineElement will also be provided by us
    // (likely the same function used in the registerElement CE's Run method)
    defineElement userProfileDef
@AngelMunoz
Copy link
Collaborator Author

current progress on this area is on #41

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant