UNPKG

@camped-ui/breadcrumb

Version:

The Breadcrumb component is a fundamental navigational element that displays a hierarchical trail of links, typically representing the user's location within a website or application. It helps users understand their current position and facilitates naviga

204 lines 11.1 kB
"use client"; "use strict"; 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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BreadcrumbContent = exports.BreadcrumbTrigger = exports.BreadcrumbPopover = exports.BreadcrumbItem = exports.BreadcrumbPage = exports.BreadcrumbList = exports.BreadcrumbSeparator = exports.BreadcrumbEllipsis = exports.BreadcrumbLink = exports.Breadcrumb = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const button_1 = require("@camped-ui/button"); const lib_1 = require("@camped-ui/lib"); const popover_1 = require("@camped-ui/popover"); const react_slot_1 = require("@radix-ui/react-slot"); const react_1 = require("react"); const BreadCrumbContext = (0, react_1.createContext)(null); const useBreadcrumb = () => { const context = (0, react_1.useContext)(BreadCrumbContext); if (!context) { throw new Error("useBreadcrumb must be used within a BreadCrumb"); } return context; }; const Breadcrumb = (_a) => { var { className, orientation = "horizontal", variant = "ghost", dir, size, children } = _a, props = __rest(_a, ["className", "orientation", "variant", "dir", "size", "children"]); const [value, setValue] = (0, react_1.useState)([]); const [prevValue, setPrevValue] = (0, react_1.useState)([]); const [activeIndex, setActiveIndex] = (0, react_1.useState)(-1); const [open, setOpen] = (0, react_1.useState)(false); const [target, setTarget] = (0, react_1.useState)(0); const handleKeyDown = (0, react_1.useCallback)((e) => { e.preventDefault(); const length = value.length - 1; const moveNext = () => { const nextIndex = activeIndex + 1 > length ? 0 : activeIndex + 1; setActiveIndex(value[nextIndex]); }; const movePrev = () => { const currentIndex = value.indexOf(activeIndex) - 1; const prevIndex = currentIndex < 0 ? length : currentIndex; setActiveIndex(value[prevIndex]); }; switch (e.key) { case "ArrowDown": if (orientation === "vertical") { moveNext(); } break; case "ArrowUp": if (orientation === "vertical") { movePrev(); } break; case "ArrowRight": if (orientation === "horizontal") { if (dir === "rtl") { movePrev(); return; } moveNext(); } break; case "ArrowLeft": if (orientation === "horizontal") { if (dir === "rtl") { moveNext(); return; } movePrev(); } break; } if (e.key === "Escape") { if (activeIndex !== -1) { if (prevValue.length > 0) setValue(prevValue); setOpen(false); if (value.includes(activeIndex) && !prevValue.includes(activeIndex) && prevValue.length > 0) { setActiveIndex(target); return; } setActiveIndex(-1); } } else if (e.key === "Enter" && activeIndex === target) { if (prevValue.length > 0) setValue(prevValue); setOpen(!open); } }, [activeIndex, value, prevValue]); return ((0, jsx_runtime_1.jsx)(BreadCrumbContext.Provider, { value: { variant, size, orientation, activeIndex, value, onValueChange: setValue, onPrevValueChange: setPrevValue, setActiveIndex, open, onOpenChange: setOpen, setTarget, }, children: (0, jsx_runtime_1.jsx)("div", Object.assign({ tabIndex: 0, onKeyDownCapture: handleKeyDown, className: (0, lib_1.cn)("flex items-center justify-center flex-wrap gap-2", { "flex-row": orientation === "horizontal", "flex-col": orientation === "vertical", }, className), dir: dir }, props, { children: children })) })); }; exports.Breadcrumb = Breadcrumb; Breadcrumb.displayName = "Breadcrumb"; const BreadcrumbItem = (0, react_1.forwardRef)((_a, ref) => { var { className, isActive, activeVariant, index, children } = _a, props = __rest(_a, ["className", "isActive", "activeVariant", "index", "children"]); const { variant, size, activeIndex, value, onValueChange, setActiveIndex, onPrevValueChange, } = useBreadcrumb(); const variants = { variant, size, }; const activeVariants = activeVariant !== null && activeVariant !== void 0 ? activeVariant : variants; const Variants = isActive ? activeVariants : variants; const isSelected = activeIndex === index; (0, react_1.useEffect)(() => { onValueChange((prev) => { if (prev.includes(index)) { return prev; } const arr = [...prev, index]; return arr.sort((a, b) => Number(a) - Number(b)); }); return () => { onPrevValueChange(value); }; }, [index, onValueChange]); return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: ref, className: (0, lib_1.cn)((0, button_1.buttonVariants)(Variants), className, isSelected ? "bg-muted focus-visible:ring-0 ring-0" : ""), onClick: () => setActiveIndex(index) }, props, { children: children }))); }); exports.BreadcrumbItem = BreadcrumbItem; BreadcrumbItem.displayName = "BreadcrumbItem"; const BreadcrumbLink = (0, react_1.forwardRef)((_a, ref) => { var { asChild, className } = _a, props = __rest(_a, ["asChild", "className"]); const Comp = asChild ? react_slot_1.Slot : "a"; return ((0, jsx_runtime_1.jsx)(Comp, Object.assign({ ref: ref, className: (0, lib_1.cn)("transition-colors hover:text-foreground", className) }, props))); }); exports.BreadcrumbLink = BreadcrumbLink; BreadcrumbLink.displayName = "BreadcrumbLink"; const BreadcrumbSeparator = (0, react_1.forwardRef)((_a, ref) => { var { className, children } = _a, props = __rest(_a, ["className", "children"]); const { orientation, dir } = useBreadcrumb(); return ((0, jsx_runtime_1.jsxs)("span", Object.assign({ ref: ref }, props, { dir: dir, "data-orientation": orientation, className: (0, lib_1.cn)("flex items-center justify-center size-4 data-[orientation='horizontal']:rotate-0 rtl:data-[orientation='horizontal']:rotate-180 data-[orientation='vertical']:rotate-90 "), children: [children ? (children) : ((0, jsx_runtime_1.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", className: (0, lib_1.cn)("h-4 w-4 ", className), children: (0, jsx_runtime_1.jsx)("path", { d: "m9 18 6-6-6-6" }) })), (0, jsx_runtime_1.jsx)("span", { className: "sr-only", children: "next page" })] }))); }); exports.BreadcrumbSeparator = BreadcrumbSeparator; BreadcrumbSeparator.displayName = "BreadcrumbSeparator"; const BreadcrumbList = (0, react_1.forwardRef)((_a, ref) => { var { className } = _a, props = __rest(_a, ["className"]); return ((0, jsx_runtime_1.jsx)("ol", Object.assign({ ref: ref, className: (0, lib_1.cn)("flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", className) }, props))); }); exports.BreadcrumbList = BreadcrumbList; BreadcrumbList.displayName = "BreadcrumbList"; const BreadcrumbPage = (0, react_1.forwardRef)((_a, ref) => { var { className } = _a, props = __rest(_a, ["className"]); return ((0, jsx_runtime_1.jsx)("span", Object.assign({ ref: ref, role: "link", "aria-disabled": "true", "aria-current": "page", className: (0, lib_1.cn)("font-normal text-foreground", className) }, props))); }); exports.BreadcrumbPage = BreadcrumbPage; BreadcrumbPage.displayName = "BreadcrumbPage"; const BreadcrumbEllipsis = (0, react_1.forwardRef)((_a, ref) => { var { className, index } = _a, props = __rest(_a, ["className", "index"]); const { activeIndex, onValueChange, setTarget } = useBreadcrumb(); const isSelected = activeIndex === index; (0, react_1.useEffect)(() => { setTarget(index); onValueChange((prev) => { if (prev.includes(index)) { return prev; } const arr = [...prev, index]; return arr.sort((a, b) => Number(a) - Number(b)); }); }, [index, onValueChange]); return ((0, jsx_runtime_1.jsxs)("span", Object.assign({ ref: ref, "aria-hidden": true, className: (0, lib_1.cn)("focus-visible:ring-0 focus-visible:ring-opacity-0", className, isSelected ? "bg-muted" : "") }, props, { children: [(0, jsx_runtime_1.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", className: "h-4 w-4 ", children: [(0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "1" }), (0, jsx_runtime_1.jsx)("circle", { cx: "19", cy: "12", r: "1" }), (0, jsx_runtime_1.jsx)("circle", { cx: "5", cy: "12", r: "1" })] }), (0, jsx_runtime_1.jsx)("span", { className: "sr-only", children: "More pages" })] }))); }); exports.BreadcrumbEllipsis = BreadcrumbEllipsis; BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis"; const BreadcrumbPopover = (0, react_1.forwardRef)(({ children }, ref) => { const { open, onOpenChange } = useBreadcrumb(); return ((0, jsx_runtime_1.jsx)(popover_1.Popover, { open: open, onOpenChange: onOpenChange, children: children })); }); exports.BreadcrumbPopover = BreadcrumbPopover; BreadcrumbPopover.displayName = "BreadcrumbPopover"; const BreadcrumbTrigger = popover_1.PopoverTrigger; exports.BreadcrumbTrigger = BreadcrumbTrigger; BreadcrumbTrigger.displayName = "BreadcrumbTrigger"; const BreadcrumbContent = (0, react_1.forwardRef)((_a, ref) => { var { children } = _a, props = __rest(_a, ["children"]); const { orientation } = useBreadcrumb(); return ((0, jsx_runtime_1.jsx)(popover_1.PopoverContent, Object.assign({}, props, { side: orientation === "horizontal" ? "bottom" : "right", ref: ref, children: children }))); }); exports.BreadcrumbContent = BreadcrumbContent; BreadcrumbContent.displayName = "BreadcrumbContent"; //# sourceMappingURL=index.js.map