rsuite
Version:
A suite of react components
76 lines (74 loc) • 2.69 kB
JavaScript
'use client';
import React from 'react';
import Button from "../Button/Button.js";
import IconButton from "../IconButton/IconButton.js";
import Badge from "../Badge/Badge.js";
import SafeAnchor from "../internals/SafeAnchor/index.js";
function getChildren(children) {
const nodes = [];
const collect = child => {
if (child === null || child === undefined || typeof child === 'boolean') {
return;
}
if (Array.isArray(child)) {
child.forEach(collect);
} else if (/*#__PURE__*/React.isValidElement(child) && child.type === React.Fragment) {
collect(child.props.children);
} else {
// Leave unknown nodes intact, including iterables that inspection could consume.
nodes.push(child);
}
};
collect(children);
return nodes;
}
function getComponentType(child) {
let type = child.type;
// A custom comparator may retain output that no longer matches the current props.
while (typeof type === 'object' && type !== null && '$$typeof' in type && type.$$typeof === Symbol.for('react.memo') && (!('compare' in type) || type.compare === null || type.compare === undefined) && 'type' in type) {
type = type.type;
}
return type;
}
function isButton(child, components) {
if (! /*#__PURE__*/React.isValidElement(child)) {
return false;
}
const type = getComponentType(child);
if (type !== Button && type !== IconButton) {
return false;
}
const props = {
...components.Button?.defaultProps,
...(type === IconButton ? components.IconButton?.defaultProps : undefined),
...child.props
};
const as = props.as || (props.href ? SafeAnchor : 'button');
if (as === SafeAnchor) {
const anchorAs = components.SafeAnchor?.defaultProps?.as;
return anchorAs === undefined || typeof anchorAs === 'string';
}
return typeof as === 'string';
}
/** Only known buttons with a single DOM root can participate in Badge group layouts. */
function isBadgeButton(children, components = {}) {
const nodes = getChildren(children);
return nodes.length === 1 && isButton(nodes[0], components);
}
/** Text and unknown component output can create anonymous grid items. */
export function canJustifyBadgeButtons(children, components = {}) {
return getChildren(children).every(child => {
if (isButton(child, components)) {
return true;
}
if (! /*#__PURE__*/React.isValidElement(child) || getComponentType(child) !== Badge) {
return false;
}
const props = {
...components.Badge?.defaultProps,
...child.props
};
return (props.as === undefined || typeof props.as === 'string') && isBadgeButton(props.children, components);
});
}
export default isBadgeButton;