@yamada-ui/breadcrumb
Version:
Yamada UI breadcrumb component
292 lines (290 loc) • 8.88 kB
JavaScript
"use client"
// src/breadcrumb.tsx
import {
forwardRef,
omitThemeProps,
ui,
useComponentMultiStyle
} from "@yamada-ui/core";
import { Icon } from "@yamada-ui/icon";
import { useValue } from "@yamada-ui/use-value";
import {
createContext,
cx,
getValidChildren,
isNumber,
runIfFunc
} from "@yamada-ui/utils";
import { cloneElement, Fragment, useCallback, useMemo } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
var [BreadcrumbProvider, useBreadcrumb] = createContext({
name: "BreadcrumbContext",
errorMessage: `useBreadcrumb returned is 'undefined'. Seems you forgot to wrap the components in "<Breadcrumb />" `
});
var Breadcrumb = forwardRef((props, ref) => {
const [styles, mergedProps] = useComponentMultiStyle("Breadcrumb", props);
const {
className,
children,
ellipsis,
endBoundaries: _endBoundaries,
gap = "fallback(2, 0.5rem)",
items = [],
separator = "/",
startBoundaries: _startBoundaries,
listProps,
separatorProps,
...rest
} = omitThemeProps(mergedProps);
let startBoundaries = useValue(_startBoundaries);
let endBoundaries = useValue(_endBoundaries);
if (startBoundaries === 0) startBoundaries = 1;
if (endBoundaries === 0) endBoundaries = 1;
if (startBoundaries) endBoundaries != null ? endBoundaries : endBoundaries = 1;
if (endBoundaries) startBoundaries != null ? startBoundaries : startBoundaries = 1;
const hasBoundaries = isNumber(startBoundaries) && isNumber(endBoundaries);
const exceed = hasBoundaries && startBoundaries + endBoundaries < items.length;
const css = {
alignItems: "center",
display: "flex",
...styles.container
};
const validChildren = getValidChildren(children);
const hasChildren = validChildren.length;
const customEllipsis = useCallback(
(providedItems) => {
if (!ellipsis) return null;
const resolvedItems = providedItems != null ? providedItems : items.slice(startBoundaries, items.length - endBoundaries);
return runIfFunc(ellipsis, { items: resolvedItems });
},
[ellipsis, endBoundaries, items, startBoundaries]
);
const cloneChildren = useMemo(() => {
if (hasChildren) {
return validChildren.map(
(child, index) => cloneElement(child, {
gap,
lastChild: validChildren.length === index + 1,
separator
})
);
} else {
let hiddenEllipsis = [];
return items.map((item, index) => {
var _a, _b, _c;
const {
name,
isCurrentPage,
currentPage = isCurrentPage,
isEllipsisPage,
ellipsisPage = isEllipsisPage,
containerProps,
...rest2
} = item;
const lastChild = items.length === index + 1;
const props2 = {
currentPage,
gap,
separator,
...containerProps
};
if (!hasBoundaries && ellipsisPage) {
hiddenEllipsis.push(item);
return lastChild ? /* @__PURE__ */ jsx(BreadcrumbItem, { ...props2, lastChild: true, children: (_a = customEllipsis([item])) != null ? _a : /* @__PURE__ */ jsx(BreadcrumbEllipsis, {}) }, index) : null;
}
if (hasBoundaries && exceed) {
const lastIndex = items.length - index - 1;
if (startBoundaries <= index && endBoundaries <= lastIndex) {
if (startBoundaries === index) {
return /* @__PURE__ */ jsx(BreadcrumbItem, { ...props2, children: (_b = customEllipsis()) != null ? _b : /* @__PURE__ */ jsx(BreadcrumbEllipsis, {}) }, index);
} else {
return null;
}
}
}
if (hiddenEllipsis.length) {
const resolvedEllipsis = (_c = customEllipsis(hiddenEllipsis)) != null ? _c : /* @__PURE__ */ jsx(BreadcrumbEllipsis, {});
hiddenEllipsis = [];
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(BreadcrumbItem, { ...props2, children: resolvedEllipsis }),
/* @__PURE__ */ jsx(BreadcrumbItem, { ...props2, lastChild, children: /* @__PURE__ */ jsx(BreadcrumbLink, { ...rest2, children: name }) })
] }, index);
} else {
return /* @__PURE__ */ jsx(BreadcrumbItem, { ...props2, lastChild, children: /* @__PURE__ */ jsx(BreadcrumbLink, { ...rest2, children: name }) }, index);
}
});
}
}, [
hasChildren,
validChildren,
separator,
gap,
items,
hasBoundaries,
exceed,
startBoundaries,
endBoundaries,
customEllipsis
]);
return /* @__PURE__ */ jsx(BreadcrumbProvider, { value: { styles, separatorProps }, children: /* @__PURE__ */ jsx(
ui.nav,
{
ref,
className: cx("ui-breadcrumb", className),
"aria-label": "Breadcrumb",
__css: styles.container,
...rest,
children: /* @__PURE__ */ jsx(ui.ol, { className: "ui-breadcrumb__list", ...listProps, __css: css, children: cloneChildren })
}
) });
});
Breadcrumb.displayName = "Breadcrumb";
Breadcrumb.__ui__ = "Breadcrumb";
var BreadcrumbItem = forwardRef(
({
className,
children,
isCurrentPage,
currentPage = isCurrentPage,
gap,
isLastChild,
lastChild = isLastChild,
separator,
separatorProps,
...rest
}, ref) => {
const { styles, separatorProps: groupSeparatorProps } = useBreadcrumb();
const validChildren = getValidChildren(children);
const cloneChildren = validChildren.map((child) => {
if (child.type === BreadcrumbLink) {
return cloneElement(child, {
currentPage
});
}
if (child.type === BreadcrumbSeparator) {
return cloneElement(child, {
children: child.props.children || separator,
gap,
...groupSeparatorProps,
...separatorProps
});
}
return child;
});
const css = {
alignItems: "center",
display: "inline-flex",
...styles.item
};
return /* @__PURE__ */ jsxs(
ui.li,
{
ref,
className: cx("ui-breadcrumb__item", className),
__css: css,
...rest,
children: [
cloneChildren,
!lastChild ? /* @__PURE__ */ jsx(
BreadcrumbSeparator,
{
gap,
...groupSeparatorProps,
...separatorProps,
children: separator
}
) : null
]
}
);
}
);
BreadcrumbItem.displayName = "BreadcrumbItem";
BreadcrumbItem.__ui__ = "BreadcrumbItem";
var BreadcrumbLink = forwardRef(
({
href,
className,
children,
isCurrentPage,
currentPage = isCurrentPage,
...rest
}, ref) => {
const { styles } = useBreadcrumb();
return /* @__PURE__ */ jsx(
ui.a,
{
ref,
as: !currentPage ? "a" : "span",
href: !currentPage ? href : void 0,
className: cx("ui-breadcrumb__link", className),
"aria-current": currentPage ? "page" : void 0,
__css: styles.link,
...rest,
children
}
);
}
);
BreadcrumbLink.displayName = "BreadcrumbLink";
BreadcrumbLink.__ui__ = "BreadcrumbLink";
var BreadcrumbSeparator = forwardRef(
({ children, gap: mx, ...rest }, ref) => {
const { styles } = useBreadcrumb();
const css = {
mx,
...styles.separator
};
return /* @__PURE__ */ jsx(
ui.span,
{
ref,
className: "ui-breadcrumb__item__separator",
__css: css,
...rest,
children
}
);
}
);
BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
BreadcrumbSeparator.__ui__ = "BreadcrumbSeparator";
var BreadcrumbEllipsis = forwardRef(
({ className, children, ...rest }, ref) => {
const { styles } = useBreadcrumb();
const css = {
...styles.ellipsis
};
return children != null ? children : /* @__PURE__ */ jsxs(
Icon,
{
ref,
className: cx("ui-breadcrumb__item__ellipsis", className),
"aria-label": "ellipsis",
stroke: "currentColor",
strokeLinecap: "round",
strokeLinejoin: "round",
strokeWidth: "1.5",
viewBox: "0 0 36 24",
xmlns: "http://www.w3.org/2000/svg",
__css: css,
...rest,
children: [
/* @__PURE__ */ jsx("circle", { cx: "10", cy: "12", fill: "currentColor", r: "2" }),
/* @__PURE__ */ jsx("circle", { cx: "20", cy: "12", fill: "currentColor", r: "2" }),
/* @__PURE__ */ jsx("circle", { cx: "30", cy: "12", fill: "currentColor", r: "2" })
]
}
);
}
);
BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";
BreadcrumbEllipsis.__ui__ = "BreadcrumbEllipsis";
export {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbSeparator,
BreadcrumbEllipsis
};
//# sourceMappingURL=chunk-E2W63VGM.mjs.map