UNPKG

@modern-kit/react

Version:
95 lines (90 loc) 3.52 kB
'use strict'; var jsxRuntime = require('react/jsx-runtime'); var hooksUseMergeRefs = require('../../hooks/useMergeRefs/index.cjs'); var React = require('react'); require('../../utils/mergeRefs/index.cjs'); require('@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__ */ jsxRuntime.jsx(SlotClone, { ...slotProps, ref: forwardedRef, children: React.isValidElement(newElement) ? React.cloneElement(newElement, void 0, newChildren) : null }); } return /* @__PURE__ */ jsxRuntime.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 = hooksUseMergeRefs.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__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }); }; function isSlottable(child) { return React.isValidElement(child) && child.type === Slottable; } exports.Slot = Slot; exports.Slottable = Slottable; //# sourceMappingURL=index.cjs.map