UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

289 lines (286 loc) 8.81 kB
// src/components/Menu/Menu.tsx import { create, useStore } from "zustand"; import { useEffect, useRef, forwardRef, isValidElement, Children, cloneElement, useState } from "react"; import { CaretLeft, CaretRight } from "phosphor-react"; // src/utils/utils.ts import { clsx } from "clsx"; import { twMerge } from "tailwind-merge"; function cn(...inputs) { return twMerge(clsx(inputs)); } // src/components/Menu/Menu.tsx import { jsx, jsxs } from "react/jsx-runtime"; var createMenuStore = (onValueChange) => create((set) => ({ value: "", setValue: (value) => { set({ value }); onValueChange?.(value); }, onValueChange })); var useMenuStore = (externalStore) => { if (!externalStore) throw new Error("MenuItem must be inside Menu"); return externalStore; }; var VARIANT_CLASSES = { menu: "bg-background shadow-soft-shadow-1 px-6", menu2: "", "menu-overflow": "", breadcrumb: "bg-transparent shadow-none !px-0" }; var Menu = forwardRef( ({ className, children, defaultValue, value: propValue, variant = "menu", onValueChange, ...props }, ref) => { const storeRef = useRef(null); storeRef.current ??= createMenuStore(onValueChange); const store = storeRef.current; const { setValue } = useStore(store, (s) => s); useEffect(() => { setValue(propValue ?? defaultValue); }, [defaultValue, propValue, setValue]); const baseClasses = variant === "menu-overflow" ? "w-fit py-2 flex flex-row items-center justify-center" : "w-full py-2 flex flex-row items-center justify-center"; const variantClasses = VARIANT_CLASSES[variant]; return /* @__PURE__ */ jsx( "div", { ref, className: ` ${baseClasses} ${variantClasses} ${className ?? ""} `, ...props, children: injectStore(children, store) } ); } ); Menu.displayName = "Menu"; var MenuContent = forwardRef( ({ className, children, variant = "menu", ...props }, ref) => { const baseClasses = "w-full flex flex-row items-center gap-2"; const variantClasses = variant === "menu2" || variant === "menu-overflow" ? "overflow-x-auto scroll-smooth" : ""; return /* @__PURE__ */ jsx( "ul", { ref, className: ` ${baseClasses} ${variantClasses} ${variant == "breadcrumb" ? "flex-wrap" : ""} ${className ?? ""} `, style: variant === "menu2" || variant === "menu-overflow" ? { scrollbarWidth: "none", msOverflowStyle: "none" } : void 0, ...props, children } ); } ); MenuContent.displayName = "MenuContent"; var MenuItem = forwardRef( ({ className, children, value, disabled = false, store: externalStore, variant = "menu", separator = false, ...props }, ref) => { const store = useMenuStore(externalStore); const { value: selectedValue, setValue } = useStore(store, (s) => s); const handleClick = (e) => { if (!disabled) { setValue(value); } props.onClick?.(e); }; const commonProps = { role: "menuitem", "aria-disabled": disabled, ref, onClick: handleClick, onKeyDown: (e) => { if (["Enter", " "].includes(e.key)) handleClick(e); }, tabIndex: disabled ? -1 : 0, onMouseDown: (e) => { e.preventDefault(); }, ...props }; const variants = { menu: /* @__PURE__ */ jsx( "li", { "data-variant": "menu", className: ` w-full flex flex-col items-center justify-center gap-0.5 py-1 px-2 rounded-sm font-medium text-xs [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text focus:outline-none focus:border-indicator-info focus:border-2 ${selectedValue === value ? "bg-primary-50 text-primary-950" : "text-text-950"} ${className ?? ""} `, ...commonProps, children } ), menu2: /* @__PURE__ */ jsxs( "li", { "data-variant": "menu2", className: ` w-full flex flex-col items-center px-2 pt-4 gap-3 cursor-pointer focus:rounded-sm justify-center hover:bg-background-100 rounded-lg focus:outline-none focus:border-indicator-info focus:border-2 ${selectedValue === value ? "" : "pb-4"} `, ...commonProps, children: [ /* @__PURE__ */ jsx( "span", { className: cn( "flex flex-row items-center gap-2 px-4 text-text-950 text-xs font-bold", className ), children } ), selectedValue === value && /* @__PURE__ */ jsx("div", { className: "h-1 w-full bg-primary-950 rounded-lg" }) ] } ), "menu-overflow": /* @__PURE__ */ jsxs( "li", { "data-variant": "menu-overflow", className: ` w-fit flex flex-col items-center px-2 pt-4 gap-3 cursor-pointer focus:rounded-sm justify-center hover:bg-background-100 rounded-lg focus:outline-none focus:border-indicator-info focus:border-2 ${selectedValue === value ? "" : "pb-4"} `, ...commonProps, children: [ /* @__PURE__ */ jsx( "span", { className: cn( "flex flex-row items-center gap-2 px-4 text-text-950 text-xs font-bold", className ), children } ), selectedValue === value && /* @__PURE__ */ jsx("div", { className: "h-1 w-full bg-primary-950 rounded-lg" }) ] } ), breadcrumb: /* @__PURE__ */ jsxs( "li", { "data-variant": "breadcrumb", className: ` flex flex-row gap-2 items-center w-fit p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs focus:outline-none focus:border-indicator-info focus:border-2 ${selectedValue === value ? "text-text-950" : "text-text-600"} ${className ?? ""} `, ...commonProps, children: [ /* @__PURE__ */ jsx( "span", { className: cn( "border-b border-text-600 hover:border-primary-600 text-inherit text-xs", selectedValue === value ? "border-b-0 font-bold" : "border-b-text-600" ), children } ), separator && /* @__PURE__ */ jsx( CaretRight, { size: 16, className: "text-text-600", "data-testid": "separator" } ) ] } ) }; return variants[variant] ?? variants["menu"]; } ); MenuItem.displayName = "MenuItem"; var injectStore = (children, store) => Children.map(children, (child) => { if (!isValidElement(child)) return child; const typedChild = child; const shouldInject = typedChild.type === MenuItem; return cloneElement(typedChild, { ...shouldInject ? { store } : {}, ...typedChild.props.children ? { children: injectStore(typedChild.props.children, store) } : {} }); }); // src/components/BreadcrumbMenu/BreadcrumbMenu.tsx import { useNavigate } from "react-router-dom"; import { jsx as jsx2 } from "react/jsx-runtime"; var BreadcrumbMenu = ({ breadcrumbs, onBreadcrumbClick, className = "!px-0 py-4 flex-wrap w-full" }) => { const navigate = useNavigate(); const handleClick = (breadcrumb, index) => { if (onBreadcrumbClick) { onBreadcrumbClick(breadcrumb, index); } navigate(breadcrumb.url); }; return /* @__PURE__ */ jsx2( Menu, { value: `breadcrumb-${breadcrumbs.length - 1}`, defaultValue: "breadcrumb-0", variant: "breadcrumb", className, children: /* @__PURE__ */ jsx2(MenuContent, { className: "w-full flex flex-row flex-wrap gap-2 !px-0", children: breadcrumbs.map((breadcrumb, index) => { const isLast = index === breadcrumbs.length - 1; const hasSeparator = !isLast; return /* @__PURE__ */ jsx2( MenuItem, { variant: "breadcrumb", value: `breadcrumb-${index}`, className: "!p-0 whitespace-nowrap", onClick: () => handleClick(breadcrumb, index), separator: hasSeparator, children: breadcrumb.name }, breadcrumb.id ); }) }) } ); }; export { BreadcrumbMenu }; //# sourceMappingURL=index.mjs.map