124 lines
3.7 KiB
TypeScript
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;
|