analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
379 lines (376 loc) • 12.9 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/components/Menu/Menu.tsx
var Menu_exports = {};
__export(Menu_exports, {
Menu: () => Menu,
MenuContent: () => MenuContent,
MenuItem: () => MenuItem,
MenuItemIcon: () => MenuItemIcon,
MenuOverflow: () => MenuOverflow,
default: () => Menu_default,
internalCheckScroll: () => internalCheckScroll,
internalScroll: () => internalScroll,
useMenuStore: () => useMenuStore
});
module.exports = __toCommonJS(Menu_exports);
var import_zustand = require("zustand");
var import_react = require("react");
var import_phosphor_react = require("phosphor-react");
// src/utils/utils.ts
var import_clsx = require("clsx");
var import_tailwind_merge = require("tailwind-merge");
function cn(...inputs) {
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
}
// src/components/Menu/Menu.tsx
var import_jsx_runtime = require("react/jsx-runtime");
var createMenuStore = (onValueChange) => (0, import_zustand.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 = (0, import_react.forwardRef)(
({
className,
children,
defaultValue,
value: propValue,
variant = "menu",
onValueChange,
...props
}, ref) => {
const storeRef = (0, import_react.useRef)(null);
storeRef.current ??= createMenuStore(onValueChange);
const store = storeRef.current;
const { setValue } = (0, import_zustand.useStore)(store, (s) => s);
(0, import_react.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__ */ (0, import_jsx_runtime.jsx)(
"div",
{
ref,
className: `
${baseClasses}
${variantClasses}
${className ?? ""}
`,
...props,
children: injectStore(children, store)
}
);
}
);
Menu.displayName = "Menu";
var MenuContent = (0, import_react.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__ */ (0, import_jsx_runtime.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 = (0, import_react.forwardRef)(
({
className,
children,
value,
disabled = false,
store: externalStore,
variant = "menu",
separator = false,
...props
}, ref) => {
const store = useMenuStore(externalStore);
const { value: selectedValue, setValue } = (0, import_zustand.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__ */ (0, import_jsx_runtime.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__ */ (0, import_jsx_runtime.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__ */ (0, import_jsx_runtime.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__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-1 w-full bg-primary-950 rounded-lg" })
]
}
),
"menu-overflow": /* @__PURE__ */ (0, import_jsx_runtime.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__ */ (0, import_jsx_runtime.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__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-1 w-full bg-primary-950 rounded-lg" })
]
}
),
breadcrumb: /* @__PURE__ */ (0, import_jsx_runtime.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__ */ (0, import_jsx_runtime.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__ */ (0, import_jsx_runtime.jsx)(
import_phosphor_react.CaretRight,
{
size: 16,
className: "text-text-600",
"data-testid": "separator"
}
)
]
}
)
};
return variants[variant] ?? variants["menu"];
}
);
MenuItem.displayName = "MenuItem";
var MenuItemIcon = ({
className,
icon,
...props
}) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"span",
{
className: cn(
"bg-background-500 w-[21px] h-[21px] flex items-center justify-center [&>svg]:w-[17px] [&>svg]:h-[17px] rounded-sm",
className
),
...props,
children: icon
}
);
var internalScroll = (container, direction) => {
if (!container) return;
container.scrollBy({
left: direction === "left" ? -150 : 150,
behavior: "smooth"
});
};
var internalCheckScroll = (container, setShowLeftArrow, setShowRightArrow) => {
if (!container) return;
const { scrollLeft, scrollWidth, clientWidth } = container;
setShowLeftArrow(scrollLeft > 0);
setShowRightArrow(scrollLeft + clientWidth < scrollWidth);
};
var MenuOverflow = ({
children,
className,
defaultValue,
value,
onValueChange,
...props
}) => {
const containerRef = (0, import_react.useRef)(null);
const [showLeftArrow, setShowLeftArrow] = (0, import_react.useState)(false);
const [showRightArrow, setShowRightArrow] = (0, import_react.useState)(false);
(0, import_react.useEffect)(() => {
const checkScroll = () => internalCheckScroll(
containerRef.current,
setShowLeftArrow,
setShowRightArrow
);
checkScroll();
const container = containerRef.current;
container?.addEventListener("scroll", checkScroll);
window.addEventListener("resize", checkScroll);
return () => {
container?.removeEventListener("scroll", checkScroll);
window.removeEventListener("resize", checkScroll);
};
}, []);
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"div",
{
"data-testid": "menu-overflow-wrapper",
className: cn("relative w-full overflow-hidden", className),
children: [
showLeftArrow && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"button",
{
onClick: () => internalScroll(containerRef.current, "left"),
className: "absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer",
"data-testid": "scroll-left-button",
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_phosphor_react.CaretLeft, { size: 16 }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: "Scroll left" })
]
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
Menu,
{
defaultValue,
onValueChange,
value,
variant: "menu2",
...props,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuContent, { ref: containerRef, variant: "menu2", children })
}
),
showRightArrow && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"button",
{
onClick: () => internalScroll(containerRef.current, "right"),
className: "absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer",
"data-testid": "scroll-right-button",
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_phosphor_react.CaretRight, { size: 16 }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: "Scroll right" })
]
}
)
]
}
);
};
var injectStore = (children, store) => import_react.Children.map(children, (child) => {
if (!(0, import_react.isValidElement)(child)) return child;
const typedChild = child;
const shouldInject = typedChild.type === MenuItem;
return (0, import_react.cloneElement)(typedChild, {
...shouldInject ? { store } : {},
...typedChild.props.children ? { children: injectStore(typedChild.props.children, store) } : {}
});
});
var Menu_default = Menu;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Menu,
MenuContent,
MenuItem,
MenuItemIcon,
MenuOverflow,
internalCheckScroll,
internalScroll,
useMenuStore
});
//# sourceMappingURL=index.js.map