UNPKG

ce-la-react

Version:

Create a React component from a custom element.

108 lines (107 loc) 4.5 kB
/** * @license * Copyright 2018 Google LLC * SPDX-License-Identifier: BSD-3-Clause * * Modified version of `@lit/react` for vanilla custom elements with support for SSR. */ import type React from 'react'; type TReact = typeof React; /** * Creates a type to be used for the props of a web component used directly in * React JSX. * * Example: * * ```ts * declare module "react" { * namespace JSX { * interface IntrinsicElements { * 'x-foo': WebComponentProps<XFoo>; * } * } * } * ``` */ export type WebComponentProps<I extends HTMLElement> = React.DetailedHTMLProps<React.HTMLAttributes<I>, I> & ElementProps<I>; export type ElementProps<I> = Partial<Omit<I, keyof HTMLElement | 'connectedCallback' | 'disconnectedCallback' | 'attributeChangedCallback' | 'adoptedCallback'>>; export type ComponentProps<I, E extends EventNames = {}> = Omit<React.HTMLAttributes<I>, keyof E | keyof ElementProps<I>> & EventListeners<E> & ElementProps<I>; /** * Type used to cast an event name with an event type when providing the * `events` option to `createComponent` for better typing of the event handler * prop. * * Example: * * ```ts * const FooComponent = createComponent({ * ... * events: { * onfoo: 'foo' as EventName<FooEvent>, * } * }); * ``` * * `onfoo` prop will have the type `(e: FooEvent) => void`. */ export type EventName<T extends Event = Event> = string & { __eventType: T; }; type EventNames = Record<string, EventName | string>; type EventListeners<R extends EventNames> = { [K in keyof R]?: R[K] extends EventName ? (e: R[K]['__eventType']) => void : (e: Event) => void; }; type CustomElementConstructor<T> = { getTemplateHTML?: (attrs: Record<string, string>, props?: Record<string, unknown>) => string; shadowRootOptions?: { mode?: string; delegatesFocus?: boolean; }; observedAttributes?: string[]; new (): T; }; export interface AttributeOptions { toAttributeName: (propName: string) => string; toAttributeValue: (propValue: unknown) => unknown | null | undefined; } export declare function defaultToAttributeName(propName: string): string; export declare function defaultToAttributeValue(propValue: unknown): unknown; export interface Options<I extends HTMLElement, E extends EventNames> extends Partial<AttributeOptions> { react: TReact; tagName: string; elementClass: CustomElementConstructor<I>; events?: E; displayName?: string; } /** * Creates a React component for a custom element. Properties are distinguished * from attributes automatically, and events can be configured so they are added * to the custom element as event listeners. * * @param options An options bag containing the parameters needed to generate a * wrapped web component. * * @param options.react The React module, typically imported from the `react` * npm package. * @param options.tagName The custom element tag name registered via * `customElements.define`. * @param options.elementClass The custom element class registered via * `customElements.define`. * @param options.events An object listing events to which the component can * listen. The object keys are the event property names passed in via React * props and the object values are the names of the corresponding events * generated by the custom element. For example, given `{onactivate: * 'activate'}` an event function may be passed via the component's `onactivate` * prop and will be called when the custom element fires its `activate` event. * @param options.displayName A React component display name, used in debugging * messages. Default value is inferred from the name of custom element class * registered via `customElements.define`. * @param options.toAttributeName A function that converts a React prop name to * a custom element attribute name. Default value is a function that converts * prop names to lower case. * @param options.toAttributeValue A function that converts a React prop value to * a custom element attribute value. Default value is a function that converts * boolean prop values to empty strings and all other primitive values to strings. */ export declare function createComponent<I extends HTMLElement, E extends EventNames = {}>({ react: React, tagName, elementClass, events, displayName, toAttributeName, toAttributeValue, }: Options<I, E>): React.ForwardRefExoticComponent<React.PropsWithoutRef<ComponentProps<I, E>> & React.RefAttributes<I>>; export {};