import {
forwardRef,
HTMLAttributes,
ForwardRefExoticComponent,
PropsWithoutRef,
RefAttributes,
ForwardRefRenderFunction,
PropsWithChildren,
} from "react";
import { CesiumContext } from "./context";
import { useCesiumComponent, Options } from "./hooks";
import { pick } from "./util";
export type CesiumComponentOptions<
Element,
Props extends RootComponentInternalProps,
State = any,
> = Options & {
renderContainer?: boolean;
noChildren?: boolean;
containerProps?: (keyof Props)[] | ((props: Props) => HTMLAttributes);
defaultProps?: Partial;
};
export type CesiumComponentRef = {
cesiumElement?: Element;
};
export type CesiumComponentType = ForwardRefExoticComponent<
PropsWithoutRef & RefAttributes>
>;
export type RootComponentInternalProps = {
onUpdate?: () => void;
};
export const createCesiumComponent = ({
renderContainer,
noChildren,
containerProps,
defaultProps,
...options
}: CesiumComponentOptions): CesiumComponentType => {
const component: ForwardRefRenderFunction, Props> = (props, ref) => {
const mergedProps = {
...defaultProps,
...props,
};
// eslint-disable-next-line react-hooks/rules-of-hooks
const [provided, mounted, wrapperRef] = useCesiumComponent(
options,
mergedProps,
ref,
);
if (noChildren) return null;
const children = mounted
? "children" in mergedProps
? (mergedProps as PropsWithChildren).children
: null
: null;
const wrappedChildren = renderContainer ? (
{children}
) : children ? (
<>{children}>
) : null;
if (provided) {
return {wrappedChildren};
}
return wrappedChildren;
};
component.displayName = options.name;
return forwardRef(component);
};