UNPKG

@crossed/primitive

Version:

A universal & performant styling library for React Native, Next.js & React

72 lines (71 loc) 2.64 kB
"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