"use client"; import { Children, Fragment, cloneElement, isValidElement, type ReactElement, type ReactNode, } from "react"; import { cx } from "../../utils"; import type { FoxBadgeSize } from "../fox-badge"; export interface FoxBadgeGroupProps { children?: ReactNode; /** 자식 배지의 `size`를 전부 이 값으로 덮어쓴다. 자식이 따로 준 값은 무시된다. */ size?: FoxBadgeSize; /** 참이면 렌더하지 않는다(DOM에 남지 않는다). */ hidden?: boolean; /** 배치 조정용. */ className?: string; } /** * 자식 배지에 그룹 크기를 강제로 덮어쓴다. FoxButtonGroup과 같은 사정이라 같은 방식이다 — * 호스트 요소는 건드리지 않고, `Children.map`이 들어가지 않는 프래그먼트는 직접 내려간다. */ function overrideChildren(children: ReactNode, size: FoxBadgeSize): ReactNode { return Children.map(children, (child) => { if (!isValidElement(child)) { return child; } if (child.type === Fragment) { const fragment = child as ReactElement<{ children?: ReactNode }>; return overrideChildren(fragment.props.children, size); } if (typeof child.type === "string") { return child; } return cloneElement(child as ReactElement>, { size }); }); } /** * @fox 배지 묶음. 배지를 가로로 늘어놓고 폭이 모자라면 줄을 넘긴다. * * `size`를 주면 안의 배지 크기가 그 값으로 통일된다. 주지 않으면 배지가 각자 정한다. * * ⚠️ 스타일은 이 파일이 import하지 않는다 — 호스트 앱이 `@use "@fox/styles/components"` * (또는 개별 파티셜)로 한 번 불러와야 한다. */ export function FoxBadgeGroup({ children, size, hidden = false, className }: FoxBadgeGroupProps) { if (hidden) { return null; } return (
{size ? overrideChildren(children, size) : children}
); }