UNPKG

@modern-kit/react

Version:
92 lines (88 loc) 3.42 kB
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