1.1.1 • Published 2 months ago

better-react-web-component v1.1.1

Weekly downloads
-
License
MIT
Repository
github
Last release
2 months ago

Better React Web Component

Wrapper for React (v18.x) Component to CustomElement that magically just works and is type safe with Typescript!

  • Small. About 1kB (minified and gzipped). Zero dependencies.
  • Simple. Each component interface is defined with strict types.
  • Good TypeScript support.
import { createCustomElement, InferProps, optional } from 'better-react-web-component'

// Define custom component interface
HelloComponent.types = {
  name: optional.string,
}

// Infer typescript types
type ComponentProps = InferProps<typeof HelloComponent.types>

// Defined component
function HelloComponent({ name = "unknown" }: ComponentProps) {
  return (
    <h1>Hello {name}!</h1>
  )
}

// Create and register custom component
customElements.define(
  "hello-component",
  createCustomElement(HelloComponent, "shadowRoot"),
)

Usage in html:

<hello-component name="World" />

Open this demo in StackBlitz

Install

npm install better-react-web-component

Guide

Define attributes

Attributes are defined on component types object.

Note Attribute names defined here are case-insensitive as they are in HTML spec! Hence the below can be used as <component name="..." /> or <component nAmE="..." />.

MyReactComponent.types = {
  name: optional.string,
  requiredName: required.string,
}

Supported prop types:

  • String: - optional.string - required.string
  • Number: - optional.number - required.number
  • Boolean: - optional.boolean - required.boolean
  • Json (parses attribute with JSON.parse): - optional.json - required.json
  • Function: - optional.event - required.event

Define default values

Default values are defined on react component itself.

function MyReactComponent({
  requiredName,
  name = "unknown",
}: InferProps<typeof MyReactComponent.types>) {
  ...
}

Handle events

This package also supports custom events to be defined.

Note Event names defined here are CASE-SENSITIVE so we lowercase them and remove leading "on" to match other event names!

import { createCustomElement, InferProps, optional } from 'better-react-web-component'
import { useState } from 'react'

InputName.types = {
  name: optional.string,
  onNameChange: optional.func, // Event name must start with "on" and will be lowercase in html land
}

function InputName({
  name = 'unknown',
  onNameChange,
}: InferProps<typeof InputName.types>) {
  const [localName, setLocalName] = useState(name)

  return (
    <input
      value={localName}
      onChange={(e) => {
        setLocalName(e.target.value)
        onNameChange?.({ detail: e.target.value }) // Trigger custom event here if it's defined
      }}
    />
  )
}

customElements.define('input-name', createCustomElement(InputName))

At the same time in html land:

<input-name name="World" />
<script>
  const inputNameEl = document.querySelector('input-name');

  // Note that event name is ALWAYS lowercase without `on` in front of it
  inputNameEl.addEventListener('namechange', (e) => {
    console.log(e.detail);
  });
</script>

Open this demo in StackBlitz

1.1.1

2 months ago

1.1.0

8 months ago

1.0.2

8 months ago

1.0.1

8 months ago

1.0.0

8 months ago

0.2.2

8 months ago

0.2.1

8 months ago

0.2.0

8 months ago

0.1.1

9 months ago

0.1.0

9 months ago