2022-08-24 23:37:08 +03:00

124 lines
3.7 KiB
TypeScript

import React, {
Fragment,
useState,
useRef,
useEffect,
FC,
isValidElement,
} from "react";
import { Dialog, Transition } from "@headlessui/react";
import { BottomSheetModal } from "components/containers/modal/BottomSheetModal";
import { BottomBarAcceptCookies } from "components/containers/modal/BottomBarAcceptCookies";
import { Button } from "components/Button/Button";
import classNames from "classnames";
import "./ColumnLayout.css";
import { Children } from "react";
import MainColumn from "./Maincolumn";
import LeftColumn from "./LeftColumn";
import RightColumn from "./RightColumn";
/* -------------------------------------------------------------------------- */
/* Custom hook to track container width */
/* -------------------------------------------------------------------------- */
const useScreenWidth = () => {
const ref: any = useRef();
const [width, setWidth] = useState<null | number>(null);
const observer = useRef(
new ResizeObserver((entries) => {
const { width } = entries[0].contentRect;
setWidth(width);
})
);
useEffect(() => {
observer.current.observe(ref.current);
}, [ref, observer]);
return [ref, width];
};
/* -------------------------------------------------------------------------- */
/* Component extentions */
/* -------------------------------------------------------------------------- */
type ColumnExtentions = {
Left: React.FC<{
children: React.ReactNode;
openLeftBar?: boolean;
widthElement?: number;
className?: string;
}>;
Main: React.FC<{
children: React.ReactNode;
className?: string;
}>;
Right: React.FC<{
children: React.ReactNode;
className?: string;
}>;
};
/* -------------------------------------------------------------------------- */
/* Component properties */
/* -------------------------------------------------------------------------- */
type ColumnLayoutProps = {
children: React.ReactNode; //Column layout gets as children not more than three children
} & Omit<React.ComponentPropsWithRef<"div">, "">;
/* -------------------------------------------------------------------------- */
/* Component function */
/* -------------------------------------------------------------------------- */
export const ColumnLayout: React.FC<ColumnLayoutProps> & ColumnExtentions = ({
children,
}) => {
const mdScreen = 768;
//Hooks
const [ref, widthElement] = useScreenWidth(); // to track width of screen
const [openLeftBar, setOpenLeftBar] = useState(false); //to open or close left bar
function leftBar() {
return setOpenLeftBar(!openLeftBar);
}
// Change openLeftBar when width of screen > 768
useEffect(() => {
if (widthElement > mdScreen) {
setOpenLeftBar(false);
}
});
// TODO
const amountChildren = React.Children.count(children);
if (amountChildren > 3) {
alert("Layout gets only 3 or lesser children");
}
const columns = React.Children.map(children, (child) => {
if (
child &&
React.isValidElement(child) &&
React.Children.only(child).type === LeftColumn
) {
return React.cloneElement(child, {
openLeftBar: openLeftBar,
widthElement: widthElement,
});
} else {
return child;
}
});
return (
<div ref={ref} className="flex">
<div className="w-full px-2 xl:px-12 column-layout-grid">
{amountChildren <= 3 ? columns : undefined}
</div>
</div>
);
};
ColumnLayout.Left = LeftColumn;
ColumnLayout.Main = MainColumn;
ColumnLayout.Right = RightColumn;