@navinc/base-react-components
Version:
Nav's Pattern Library
72 lines (71 loc) • 3.46 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { jsx as _jsx } from "react/jsx-runtime";
/*
Code copied and modified from https://github.com/radix-ui/primitives/issues/1825#issuecomment-1577723288
This is not a solid API and subject to change if a maintained implementation is found, so let's keep it internal.
Not using radix-ui's Slot primitive as it does not support nested Slottables.
*/
import { composeRefs } from '@radix-ui/react-compose-refs';
import { forwardRef, Children, cloneElement, isValidElement, } from 'react';
function mergeProps(slotProps, childProps) {
// all child props should override
const overrideProps = Object.assign({}, childProps);
for (const propName in childProps) {
const slotPropValue = slotProps[propName];
const childPropValue = childProps[propName];
const isHandler = /^on[A-Z]/.test(propName);
if (isHandler) {
// if the handler exists on both, we compose them
if (slotPropValue && childPropValue) {
overrideProps[propName] = (...args) => {
childPropValue(...args);
slotPropValue(...args);
};
}
// but if it exists only on the slot, we use only this one
else if (slotPropValue) {
overrideProps[propName] = slotPropValue;
}
}
// if it's `style`, we merge them
else if (propName === 'style') {
overrideProps[propName] = Object.assign(Object.assign({}, slotPropValue), childPropValue);
}
else if (propName === 'className') {
overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(' ');
}
}
return Object.assign(Object.assign({}, slotProps), overrideProps);
}
const SlotClone = forwardRef((props, forwardedRef) => {
const { children } = props, slotProps = __rest(props, ["children"]);
if (isValidElement(children)) {
return cloneElement(children, Object.assign(Object.assign({}, mergeProps(slotProps, children.props)), { ['ref']: forwardedRef ? composeRefs(forwardedRef, children.ref) : children.ref }));
}
return Children.count(children) > 1 ? Children.only(null) : null;
});
SlotClone.displayName = 'SlotClone';
const Slot = forwardRef((props, forwardedRef) => {
const { asChild, child, children, defaultComponent } = props, slotProps = __rest(props, ["asChild", "child", "children", "defaultComponent"]);
const Component = asChild ? SlotClone : defaultComponent;
/* eslint-disable no-nested-ternary -- copied code */
return (_jsx(Component, Object.assign({}, slotProps, { ref: forwardedRef, children: asChild
? isValidElement(child)
? cloneElement(child, undefined, children(child.props.children))
: null
: children(child) })));
/* eslint-enable no-nested-ternary -- copied code */
});
Slot.displayName = 'Slot';
export { Slot };
//# sourceMappingURL=slot.js.map