@codeworker.br/govbr-tw-react
Version:
Biblioteca de componentes React usando Tailwind CSS que implementa o Padrão Digital de Governo.
181 lines (180 loc) • 9.24 kB
JavaScript
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;
};
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { createContext, forwardRef, useContext, useEffect, useImperativeHandle, useLayoutEffect, useRef, } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faXmark } from "@fortawesome/free-solid-svg-icons";
import { Button } from "../Button";
import BASE_CLASSNAMES from "../../config/baseClassNames";
import { cn } from "../../libs/utils";
import { sheetViewportVariants, sheetContentVariants, sheetHeaderVariants, sheetBodyVariants, sheetFooterVariants, } from "./variants";
const TRANSITION_DURATION = 300;
const SheetContext = createContext(null);
const useSheetContext = () => {
const context = useContext(SheetContext);
if (!context) {
throw new Error("Sheet compound components must be used within Sheet.");
}
return context;
};
const closeButtonVariantByTheme = {
default: "ghost",
dark: "ghost-dark",
};
const overlayFallbackClassByVariant = {
default: "backdrop:bg-black/50",
dark: "backdrop:bg-govbr-blue-warm-vivid-90/80", // exemplo de overlay customizado usando Tailwind
};
const SheetClose = forwardRef((_a, ref) => {
var { className, variant, onClick, type } = _a, props = __rest(_a, ["className", "variant", "onClick", "type"]);
const { toggleDialog, variant: sheetVariant } = useSheetContext();
return (_jsx(Button, Object.assign({ ref: ref, type: type !== null && type !== void 0 ? type : "button", size: "icon", variant: variant !== null && variant !== void 0 ? variant : closeButtonVariantByTheme[sheetVariant], onClick: (event) => {
onClick === null || onClick === void 0 ? void 0 : onClick(event);
if (event.defaultPrevented) {
return;
}
toggleDialog();
}, className: cn(BASE_CLASSNAMES.sheet.close, className) }, props, { children: _jsx(FontAwesomeIcon, { icon: faXmark }) })));
});
SheetClose.displayName = "SheetClose";
const SheetForwardRef = forwardRef((_a, ref) => {
var { children, toggleDialog, side, variant, padding = true, density, persist, closeOnEsc, showCloseButton = true, containerClassName, className, overlayClassName, closeButtonLabel = "Fechar painel", closeButtonProps } = _a, dialogProps = __rest(_a, ["children", "toggleDialog", "side", "variant", "padding", "density", "persist", "closeOnEsc", "showCloseButton", "containerClassName", "className", "overlayClassName", "closeButtonLabel", "closeButtonProps"]);
const resolvedVariant = (variant !== null && variant !== void 0 ? variant : "default");
const resolvedSide = (side !== null && side !== void 0 ? side : "left");
const resolvedDensity = density !== null && density !== void 0 ? density : (padding ? "relaxed" : "none");
const resolvedOverlayClassName = cn("bg-transparent", overlayFallbackClassByVariant[resolvedVariant], overlayClassName);
const dialogRef = useRef(null);
const panelRef = useRef(null);
useImperativeHandle(ref, () => dialogRef.current, []);
useEffect(() => {
const dialog = dialogRef.current;
if (!dialog) {
return;
}
const handleCancel = (event) => {
if (closeOnEsc === false) {
event.preventDefault();
}
};
dialog.addEventListener("cancel", handleCancel);
return () => {
dialog.removeEventListener("cancel", handleCancel);
};
}, [closeOnEsc]);
useLayoutEffect(() => {
const dialog = dialogRef.current;
if (!dialog) {
return;
}
const marker = "__govbr_sheet_patched__";
if (dialog[marker]) {
return;
}
dialog[marker] = true;
const originalShowModal = dialog.showModal.bind(dialog);
const originalClose = dialog.close.bind(dialog);
let closeTimer = null;
dialog.showModal = (...args) => {
if (closeTimer) {
window.clearTimeout(closeTimer);
closeTimer = null;
}
const panel = panelRef.current;
if (panel) {
panel.dataset.motion = "opening";
void panel.getBoundingClientRect();
}
const result = originalShowModal(...args);
requestAnimationFrame(() => {
const currentPanel = panelRef.current;
if (currentPanel) {
currentPanel.dataset.motion = "open";
}
});
return result;
};
dialog.close = (returnValue) => {
const panel = panelRef.current;
if (!panel) {
originalClose(returnValue);
return;
}
if (panel.dataset.motion === "closing") {
return;
}
panel.dataset.motion = "closing";
if (closeTimer) {
window.clearTimeout(closeTimer);
}
closeTimer = window.setTimeout(() => {
panel.dataset.motion = "closed";
originalClose(returnValue);
closeTimer = null;
}, TRANSITION_DURATION);
};
return () => {
if (closeTimer) {
window.clearTimeout(closeTimer);
}
dialog.showModal = originalShowModal;
dialog.close = originalClose;
delete dialog[marker];
};
}, []);
useLayoutEffect(() => {
var _a;
const panel = panelRef.current;
if (!panel) {
return;
}
if (!panel.dataset.motion) {
panel.dataset.motion = "closed";
}
if ((_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.open) {
panel.dataset.motion = "open";
}
}, []);
const _b = closeButtonProps !== null && closeButtonProps !== void 0 ? closeButtonProps : {}, { className: closeButtonClassName } = _b, closeButtonRest = __rest(_b, ["className"]);
const { onClick: dialogOnClick } = dialogProps, restDialogProps = __rest(dialogProps, ["onClick"]);
return (_jsx("dialog", Object.assign({ ref: dialogRef, className: resolvedOverlayClassName, onClick: (event) => {
dialogOnClick === null || dialogOnClick === void 0 ? void 0 : dialogOnClick(event);
if (event.defaultPrevented) {
return;
}
if (!persist && event.currentTarget === event.target) {
toggleDialog();
}
} }, restDialogProps, { children: _jsx(SheetContext.Provider, { value: { variant: resolvedVariant, side: resolvedSide, density: resolvedDensity, toggleDialog }, children: _jsx("div", { className: cn(sheetViewportVariants({ side: resolvedSide }), containerClassName, BASE_CLASSNAMES.sheet.root, BASE_CLASSNAMES.sheet.container), children: _jsxs("div", { ref: (node) => {
panelRef.current = node;
}, className: cn(sheetContentVariants({ side: resolvedSide, variant: resolvedVariant }), className, BASE_CLASSNAMES.sheet.panel), "data-side": resolvedSide, children: [showCloseButton ? (_jsx(SheetClose, Object.assign({ "aria-label": closeButtonLabel, className: cn("absolute right-4 top-4", closeButtonClassName) }, closeButtonRest))) : null, _jsx("div", { className: "flex h-full flex-col", "data-side": resolvedSide, children: children })] }) }) }) })));
});
SheetForwardRef.displayName = "Sheet";
const SheetHeader = forwardRef((_a, ref) => {
var { className } = _a, props = __rest(_a, ["className"]);
const { variant, density } = useSheetContext();
return (_jsx("header", Object.assign({ ref: ref, className: cn(sheetHeaderVariants({ variant, density }), className, BASE_CLASSNAMES.sheet.header) }, props)));
});
SheetHeader.displayName = "SheetHeader";
const SheetMain = forwardRef((_a, ref) => {
var { className } = _a, props = __rest(_a, ["className"]);
const { density } = useSheetContext();
return (_jsx("main", Object.assign({ ref: ref, className: cn(sheetBodyVariants({ density }), className, BASE_CLASSNAMES.sheet.main) }, props)));
});
SheetMain.displayName = "SheetMain";
const SheetFooter = forwardRef((_a, ref) => {
var { className } = _a, props = __rest(_a, ["className"]);
const { variant, density } = useSheetContext();
return (_jsx("footer", Object.assign({ ref: ref, className: cn(sheetFooterVariants({ variant, density }), className, BASE_CLASSNAMES.sheet.footer) }, props)));
});
SheetFooter.displayName = "SheetFooter";
const Sheet = Object.assign(Object.assign({}, SheetForwardRef), { Header: SheetHeader, Main: SheetMain, Footer: SheetFooter, Close: SheetClose });
export default Sheet;