NavBar.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Copyright 2021-2024 Avaiga Private Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  5. * the License. You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  10. * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11. * specific language governing permissions and limitations under the License.
  12. */
  13. import React, { useCallback, useContext, useMemo, useState } from "react";
  14. import Tabs from "@mui/material/Tabs";
  15. import Tab from "@mui/material/Tab";
  16. import Box from "@mui/material/Box";
  17. import List from "@mui/material/List";
  18. import ListItemButton from "@mui/material/ListItemButton";
  19. import ListItemText from "@mui/material/ListItemText";
  20. import Drawer from "@mui/material/Drawer";
  21. import IconButton from "@mui/material/IconButton";
  22. import Tooltip from "@mui/material/Tooltip";
  23. import Menu from "@mui/icons-material/Menu";
  24. import { useLocation, useNavigate } from "react-router";
  25. import Link from "./Link";
  26. import { LovProps, useLovListMemo, LovImage } from "./lovUtils";
  27. import { useClassNames, useDynamicProperty, useIsMobile } from "../../utils/hooks";
  28. import { TaipyContext } from "../../context/taipyContext";
  29. import { LovItem } from "../../utils/lov";
  30. import { getBaseURL } from "../../utils";
  31. import { getComponentClassName } from "./TaipyStyle";
  32. const boxSx = { borderBottom: 1, borderColor: "divider", width: "fit-content" };
  33. const NavBar = (props: LovProps) => {
  34. const { id } = props;
  35. const { state } = useContext(TaipyContext);
  36. const active = useDynamicProperty(props.active, props.defaultActive, true);
  37. const location = useLocation();
  38. const navigate = useNavigate();
  39. const isMobile = useIsMobile();
  40. const [opened, setOpened] = useState(false);
  41. const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
  42. const hover = useDynamicProperty(props.hoverText, props.defaultHoverText, undefined);
  43. const lovList = useLovListMemo(props.lov, props.defaultLov || "");
  44. const lov = useMemo(() => {
  45. if (!lovList.length) {
  46. return Object.keys(state.locations || {})
  47. .filter((key) => key !== "/")
  48. .map((key) => ({ id: key, item: state.locations[key].substring(1) } as LovItem));
  49. }
  50. return lovList;
  51. }, [lovList, state.locations]);
  52. const linkChange = useCallback(
  53. (evt: React.SyntheticEvent, val: string) => {
  54. if (Object.keys(state.locations || {}).some((route) => val === route)) {
  55. navigate(getBaseURL() + val.substring(1));
  56. } else {
  57. window.open(val, "_blank")?.focus();
  58. }
  59. },
  60. [state.locations, navigate]
  61. );
  62. const selectedVal =
  63. lov.find((it) => getBaseURL() + it.id.substring(1) === location.pathname)?.id ||
  64. (lov.length ? lov[0].id : false);
  65. return isMobile ? (
  66. <Tooltip title={hover || ""}>
  67. <>
  68. <Drawer
  69. open={opened}
  70. onClose={() => setOpened(false)}
  71. className={`${className} ${getComponentClassName(props.children)}`}
  72. >
  73. <List>
  74. {lov.map((val) => (
  75. <ListItemButton
  76. key={val.id}
  77. onClick={() => setOpened(false)}
  78. disabled={!active}
  79. selected={selectedVal === val.id}
  80. >
  81. <ListItemText>
  82. <Link href={val.id}>
  83. {typeof val.item === "string" ? val.item : <LovImage item={val.item} />}
  84. </Link>
  85. </ListItemText>
  86. </ListItemButton>
  87. ))}
  88. </List>
  89. </Drawer>
  90. <IconButton onClick={() => setOpened((o) => !o)}>
  91. <Menu />
  92. </IconButton>
  93. {props.children}
  94. </>
  95. </Tooltip>
  96. ) : (
  97. <Box sx={boxSx} className={`${className} ${getComponentClassName(props.children)}`}>
  98. <Tooltip title={hover || ""}>
  99. <Tabs value={selectedVal} id={id} onChange={linkChange}>
  100. {lov.map((val) => (
  101. <Tab
  102. key={val.id}
  103. value={val.id}
  104. disabled={!active}
  105. label={typeof val.item === "string" ? val.item : <LovImage item={val.item} />}
  106. />
  107. ))}
  108. </Tabs>
  109. </Tooltip>
  110. {props.children}
  111. </Box>
  112. );
  113. };
  114. export default NavBar;