@modern-kit/react
Version:
92 lines (88 loc) • 3.42 kB
JavaScript
import { jsx, Fragment } from 'react/jsx-runtime';
import { useMergeRefs } from '../../hooks/useMergeRefs/index.mjs';
import React from 'react';
import '../../utils/mergeRefs/index.mjs';
import '@modern-kit/utils';
function mergeProps(slotProps, childProps) {
const overrideProps = { ...childProps };
for (const propName in childProps) {
const slotPropValue = slotProps[propName];
const childPropValue = childProps[propName];
const isHandler = /^on[A-Z]/.test(propName);
if (isHandler) {
if (slotPropValue && childPropValue) {
overrideProps[propName] = (...args) => {
childPropValue(...args);
slotPropValue(...args);
};
} else if (slotPropValue) {
overrideProps[propName] = slotPropValue;
}
} else if (propName === "style") {
overrideProps[propName] = { ...slotPropValue, ...childPropValue };
} else if (propName === "className") {
overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" ");
}
}
return { ...slotProps, ...overrideProps };
}
function getElementRef(element) {
let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get;
let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
if (mayWarn) {
return element.ref;
}
getter = Object.getOwnPropertyDescriptor(element, "ref")?.get;
mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
if (mayWarn) {
return element.props.ref;
}
return element.props.ref || element.ref;
}
const Slot = React.forwardRef(
(props, forwardedRef) => {
const { children, ...slotProps } = props;
const childrenArray = React.Children.toArray(children);
const slottable = childrenArray.find(isSlottable);
if (slottable) {
const newElement = slottable.props.children;
const newChildren = childrenArray.map((child) => {
if (child === slottable) {
if (React.Children.count(newElement) > 1) {
return React.Children.only(null);
}
return React.isValidElement(newElement) ? newElement.props.children : null;
}
return child;
});
return /* @__PURE__ */ jsx(SlotClone, { ...slotProps, ref: forwardedRef, children: React.isValidElement(newElement) ? React.cloneElement(newElement, void 0, newChildren) : null });
}
return /* @__PURE__ */ jsx(SlotClone, { ...slotProps, ref: forwardedRef, children });
}
);
Slot.displayName = "Slot";
const SlotClone = React.forwardRef(
(props, forwardedRef) => {
const { children, ...slotProps } = props;
const childRef = React.isValidElement(children) ? getElementRef(children) : null;
const mergedRefs = useMergeRefs(forwardedRef, childRef);
if (!React.isValidElement(children)) {
return React.Children.count(children) > 1 ? React.Children.only(null) : null;
}
return React.cloneElement(children, {
...mergeProps(slotProps, children.props),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
ref: forwardedRef ? mergedRefs : childRef
});
}
);
SlotClone.displayName = "SlotClone";
const Slottable = ({ children }) => {
return /* @__PURE__ */ jsx(Fragment, { children });
};
function isSlottable(child) {
return React.isValidElement(child) && child.type === Slottable;
}
export { Slot, Slottable };
//# sourceMappingURL=index.mjs.map