UNPKG

@lit/react

Version:

A React component wrapper for web components.

89 lines (87 loc) 3.58 kB
/** * @license * Copyright 2018 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ const reservedReactProperties = new Set([ 'children', 'localName', 'ref', 'style', 'className', ]); /** * 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`. */ const createComponent = ({ react: React, tagName, elementClass, events, displayName, }) => { const eventProps = new Set(Object.keys(events ?? {})); const ReactComponent = React.forwardRef((props, ref) => { React.useRef(new Map()); const elementRef = React.useRef(null); // Props to be passed to React.createElement const reactProps = {}; // Props to be set on element with setProperty const elementProps = {}; for (const [k, v] of Object.entries(props)) { if (reservedReactProperties.has(k)) { // React does *not* handle `className` for custom elements so // coerce it to `class` so it's handled correctly. reactProps[k === 'className' ? 'class' : k] = v; continue; } if (eventProps.has(k) || k in elementClass.prototype) { elementProps[k] = v; continue; } reactProps[k] = v; } { // If component is to be server rendered with `@lit/ssr-react`, pass // element properties in a special bag to be set by the server-side // element renderer. if ((React.createElement.name === 'litPatchedCreateElement' || globalThis.litSsrReactEnabled) && Object.keys(elementProps).length) { // This property needs to remain unminified. reactProps['_$litProps$'] = elementProps; } } return React.createElement(tagName, { ...reactProps, ref: React.useCallback((node) => { elementRef.current = node; if (typeof ref === 'function') { ref(node); } else if (ref !== null) { ref.current = node; } }, [ref]), }); }); ReactComponent.displayName = displayName ?? elementClass.name; return ReactComponent; }; export { createComponent }; //# sourceMappingURL=create-component.js.map