Home

web-component-wrapper 0.0.602

Project status

npm npm downloads

build build push package

check types lint test

code coverage

deploy web documentation web documentation

Use case

Encapsulate your components as web-components.

Content

Installation

You can install via package manager, simply download the compiled version as zip file here and inject or request via cdn in HTML:

npm install web-component-wrapper
import {func, object} from 'clientnode/property-types'
import {property} from 'web-component-wrapper/decorator'
import {Web} from 'web-component-wrapper/Web'

export class MyWebComponent<
    TElement = HTMLElement,
    ExternalProperties extends Mapping<unknown> = Mapping<unknown>,
    InternalProperties extends Mapping<unknown> = Mapping<unknown>
> extends Web<TElement, ExternalProperties, InternalProperties> {
    static content = `
        <div class="wrapper" on-click="this.rootInstance.onClick(event)">
            <slot>Please provide a template to transclude.</slot>
        </div>
    `
    
    @property({type: object})
    options = {} as Options

    @property({type: func})
    onClick: (event: MouseEvent) => Promise<void> = NOOP
    /**
     * Defines dynamic getter and setter interface and resolves a configuration
     * object. Initializes the map implementation.
     */
    constructor() {
        super()
        /*
            Babel property declaration transformation overwrites defined
            properties at the end of an implicit constructor. So we have to
            redefine them as long as we want to declare expected component
            interface properties to enable static type checks.
        */
        this.defineGetterAndSetterInterface()
    }
    /**
     * Triggered when ever a given attribute has changed and triggers to update
     * configured dom content.
     * @param name - Attribute name which was updates.
     * @param newValue - New updated value.
     * @returns Returns when attribute has been updated.
     */
    async onUpdateAttribute(name: string, newValue: string): Promise<void> {
        await super.onUpdateAttribute(name, newValue)

        // ...
    }
    /**
     * Updates controlled dom elements.
     * @param reason - Why an update has been triggered.
     * @param resolveRendering - Indicates whether rendering should be resolved
     * finally. Should be set to "false" via super calls in inherited render
     * methods which do further dom manipulations afterward and resolve the
     * rendering process by their own.
     * @returns A promise resolving when rendering has finished. A promise may
     * be needed for classes inheriting from this class.
     */
    async render(reason = 'unknown', resolveRendering = true): Promise<void> {
        await super.render(reason, false)

        await this.waitForNestedComponentRendering()

        // ...

        await this.resolveRenderingPromiseIfSet(reason, resolveRendering)
    }
    
    // ...
}

customElements.define('my-web-component', MyWebComponent)

Examples

Load via CDN

<script
    src="https://unpkg.com/web-component-wrapper@latest/dist/bundle/index.js"
></script>

Simple Web-Component

class MyGreeting extends webComponentWrapper.Web {
    static doRender = true
    static evaluateSlots = true
    static determineRootBinding = false
    static content = '<div>Hello ${rootInstance.greetingName}</div>'
}
// Alternative to the decorator syntax:
webComponentWrapper.property()({self: MyGreeting}, 'greetingName')

customElements.define('my-greeting', MyGreeting)
<my-greeting greeting-name="World"></my-greeting>

Simple React-Web-Component

class MyReactGreeting extends webComponentWrapper.ReactWeb {
    static doRender = true
    static evaluateSlots = true
    // Content has a react component to wrap.
    static content = ({name}) => <div>Hello {name}</div>
}
// Alternative to the decorator syntax:
webComponentWrapper.property()({self: MyReactGreeting}, 'name')

customElements.define('my-react-greeting', MyReactGreeting)

Data-Flow

Data can flow into a component via

  • External property set instance.value = 'value'
  • Trigger Events instance.triggerEvent('click')

Data can be communicated back via:

  • Properties log.info(instance.value)
  • Observable events instance.addEventListener('click', (event) => console.log(event.detail.value))

Configuring Data-Flow

A Web-Component-Wrapper component forwards (transformed) given properties into a wrapped React component via props and reads data via provided callbacks as part of props or as part of reacts ref object.