@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
JavaScript
"use client";
;
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