@crossed/primitive
Version:
A universal & performant styling library for React Native, Next.js & React
72 lines (71 loc) • 2.64 kB
JavaScript
"use client";
import { Fragment, jsx } from "react/jsx-runtime";
import { composeRefs } from "@crossed/core";
import * as React from "react";
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;
} else {
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;
if (React.isValidElement(children)) {
return React.cloneElement(children, {
...mergeProps(slotProps, children.props),
ref: forwardedRef ? composeRefs(forwardedRef, children.ref) : children.ref
});
}
return React.Children.count(children) > 1 ? React.Children.only(null) : null;
}
);
SlotClone.displayName = "SlotClone";
const Slottable = ({ children }) => {
return /* @__PURE__ */ jsx(Fragment, { children });
};
function isSlottable(child) {
return React.isValidElement(child) && child.type === Slottable;
}
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 };
}
export {
Slot,
Slottable
};
//# sourceMappingURL=Slot.js.map