/**
 * @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
