TocPath.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import { useNavigate, useSearchParams } from "react-router-dom";
  2. import { Breadcrumb, MenuProps, Popover, Tag, Typography } from "antd";
  3. import PaliText from "../template/Wbw/PaliText";
  4. import React, { useEffect, useState } from "react";
  5. import { fullUrl } from "../../utils";
  6. export interface ITocPathNode {
  7. key?: string;
  8. book?: number;
  9. paragraph?: number;
  10. title: string;
  11. paliTitle?: string;
  12. level: number;
  13. menu?: MenuProps["items"];
  14. }
  15. export declare type ELinkType = "none" | "blank" | "self";
  16. interface IWidgetTocPath {
  17. data?: ITocPathNode[];
  18. trigger?: React.ReactNode;
  19. link?: ELinkType;
  20. channel?: string[];
  21. style?: React.CSSProperties;
  22. onChange?: Function;
  23. onMenuClick?: Function;
  24. }
  25. const TocPathWidget = ({
  26. data = [],
  27. trigger,
  28. link = "self",
  29. channel,
  30. style,
  31. onChange,
  32. onMenuClick,
  33. }: IWidgetTocPath): JSX.Element => {
  34. const [currData, setCurrData] = useState(data);
  35. const navigate = useNavigate();
  36. const [searchParams] = useSearchParams();
  37. console.debug("TocPathWidget render");
  38. useEffect(() => setCurrData(data), [data]);
  39. const fullPath = (
  40. <Breadcrumb
  41. style={{ whiteSpace: "nowrap", width: "100%", fontSize: style?.fontSize }}
  42. >
  43. {currData.map((item, id) => {
  44. return (
  45. <Breadcrumb.Item
  46. menu={
  47. item.menu
  48. ? {
  49. items: item.menu,
  50. onClick: (e) => {
  51. if (typeof onMenuClick !== "undefined") {
  52. onMenuClick(e.key);
  53. }
  54. },
  55. }
  56. : undefined
  57. }
  58. onClick={(
  59. e: React.MouseEvent<
  60. HTMLSpanElement | HTMLAnchorElement,
  61. MouseEvent
  62. >
  63. ) => {
  64. if (typeof onChange !== "undefined") {
  65. onChange(item, e);
  66. } else {
  67. if (item.book && item.paragraph) {
  68. const type = item.level < 8 ? "chapter" : "para";
  69. const param =
  70. type === "para"
  71. ? `&book=${item.book}&par=${item.paragraph}`
  72. : "";
  73. const channel = searchParams.get("channel");
  74. const mode = searchParams.get("mode");
  75. const urlMode = mode ? mode : "read";
  76. let url = `/article/${type}/${item.book}-${item.paragraph}?mode=${urlMode}${param}`;
  77. url += channel ? `&channel=${channel}` : "";
  78. if (e.ctrlKey || e.metaKey) {
  79. window.open(fullUrl(url), "_blank");
  80. } else {
  81. navigate(url);
  82. }
  83. }
  84. }
  85. }}
  86. key={id}
  87. >
  88. <Typography.Link>
  89. {item.level < 99 ? (
  90. <span
  91. style={
  92. item.level === 0
  93. ? {
  94. padding: "0 4px",
  95. backgroundColor: "rgba(128, 128, 128, 0.2)",
  96. borderRadius: 4,
  97. }
  98. : undefined
  99. }
  100. >
  101. <PaliText text={item.title} />
  102. </span>
  103. ) : (
  104. <Tag>{item.title}</Tag>
  105. )}
  106. </Typography.Link>
  107. </Breadcrumb.Item>
  108. );
  109. })}
  110. </Breadcrumb>
  111. );
  112. if (typeof trigger === "undefined") {
  113. return fullPath;
  114. } else {
  115. return (
  116. <Popover placement="bottomRight" title={fullPath}>
  117. {trigger}
  118. </Popover>
  119. );
  120. }
  121. };
  122. export default TocPathWidget;