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

Type Definitions for React CustomEvents #296

Closed
AykutSarac opened this issue Oct 19, 2022 · 11 comments · Fixed by #449
Closed

Type Definitions for React CustomEvents #296

AykutSarac opened this issue Oct 19, 2022 · 11 comments · Fixed by #449
Labels
bug Something isn't working react Issues related with React wrapper released on @beta released

Comments

@AykutSarac
Copy link
Member

AykutSarac commented Oct 19, 2022

Describe the bug
EventHandler properties are not shown for CustomEvents on React & TypeScript

To Reproduce
Steps to reproduce the behavior:

  1. Create <BlSelect /> component
  2. Add onSelect
  3. On onSelect={e => ...} you won't be able to see custom properties of Event Handler referenced as "e" however it can be accessed

Versions
Baklava v2.0.0-beta.38
React 18.2.0

@leventozen leventozen added bug Something isn't working baklava-ds labels Oct 19, 2022
@AykutSarac
Copy link
Member Author

AykutSarac commented Nov 1, 2022

I'm currently looking into it. From what I've seen so far is ,each @property definition should be added into the CustomEvent interface's parameter.

EDIT: welp, not exactly what I expected. I'll see if I could create a fix for that and open a PR.

@AykutSarac
Copy link
Member Author

Could it be because the dispatcher function takes an interface <T> for event decleration however it was not referenced while emitting? https://github.com/Trendyol/baklava/blob/next/src/utilities/event.ts#L30

So in this case it should be updated with the following?

export function event<T>(customName?: string) {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  return (protoOrDescriptor: any, name: string): any => {
    const descriptor = {
      get(this: HTMLElement) {
        return dispatcher<T>(this, customName || name);
      },
      enumerable: true,
      configurable: true,
    };

    Object.defineProperty(protoOrDescriptor, name, descriptor);
  };
}

and while declaring events
from this:
@event('bl-change') private onChange: EventDispatcher<string>;
to this:
@event<string>('bl-change') private onChange: EventDispatcher<string>;

Haven't tested yet so not sure if it will work though, just an idea.

@muratcorlu muratcorlu added the react Issues related with React wrapper label Feb 7, 2023
@muratcorlu
Copy link
Contributor

@AykutSarac is this issue still valid?

@AykutSarac
Copy link
Member Author

Yes

@muratcorlu
Copy link
Contributor

Apparently we can set event types like defined here: https://github.com/lit/lit/tree/main/packages/labs/react#typescript

I'll try to prioritize this.

@AykutSarac
Copy link
Member Author

Apparently we can set event types like defined here: https://github.com/lit/lit/tree/main/packages/labs/react#typescript

I'll try to prioritize this.

That's awesome, let me know if anything that I can contribute!

@muratcorlu
Copy link
Contributor

muratcorlu commented Feb 24, 2023

I quickly checked the complexity. Here is what I could find:

For having simple event types, it looks easy to set them. Our component analyzer already parses event types. An example from Textarea component1:

{
  "kind": "class",
  "description": "",
  "name": "BlTextarea",
  "events": [
    {
      "type": {
        "text": "CustomEvent<string>"
      },
      "name": "bl-input"
    },
    {
      "type": {
        "text": "CustomEvent<string>"
      },
      "name": "bl-change"
    },
    {
      "type": {
        "text": "CustomEvent<EventDispatcher<ValidityState>>"
      },
      "name": "bl-invalid"
    }
  ],
 ....

We can simply put type.text to the next of event names in baklava-react.ts like described in lit-labs/react documentation. Like:

export const BlTextarea = React.lazy(() =>
  customElements.whenDefined("bl-textarea").then((elem) => ({
    default: createComponent<BlTextareaType>({
      react: React,
      tagName: "bl-textarea",
      elementClass: elem,
      events: {
        onInput: "bl-input" as EventName<CustomEvent<string>>,
        onChange: "bl-change" as EventName<CustomEvent<string>>,
        onInvalid: "bl-invalid" as EventName<CustomEvent<ValidityState>>,
      },
    }),
  }))
);

This can already improve the experience a lot, but currently, I used more advanced event types in my PR for select component and this approach will not be enough for setting types for that. Because Select will accept custom types for its values and its event will provide the selected item with its custom type. So we'll need to use Generic types together with React.lazy. Adding generic types to our Baklava React wrappers is the challenge here and I couldn't find a quick solution for now.

Footnotes

  1. You may notice another issue here that bl-invalid event has EventDispatcher type as well, which is wrong. This is another problem that we need to fix but I believe it'll not be that much challenging.

@muratcorlu
Copy link
Contributor

I included this (in a better way, IMO) in my PR about event names: #449 @AykutSarac Please have a look if it works for you.

@AykutSarac
Copy link
Member Author

Works very well, thank you!

@github-actions
Copy link

github-actions bot commented Mar 1, 2023

🎉 This issue has been resolved in version 2.0.0-beta.77 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions
Copy link

github-actions bot commented Apr 6, 2023

🎉 This issue has been resolved in version 2.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working react Issues related with React wrapper released on @beta released
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants