UNPKG

@yamada-ui/breadcrumb

Version:

Yamada UI breadcrumb component

292 lines (290 loc) • 8.88 kB
"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