You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
2.4 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. import React, {PropsWithChildren, useCallback, useEffect} from "react";
  2. import ReactModal from "react-modal";
  3. import "./Layout.sass";
  4. import {LuciferIcon} from "../models/Icons";
  5. import {IconBlock} from "./Elements";
  6. interface TabsProps {
  7. tabNames: string[]
  8. index: number
  9. onChange: (newIndex: number) => void
  10. boldIndex?: number
  11. large?: boolean
  12. }
  13. export function Tabs({tabNames, index, onChange, large, boldIndex}: TabsProps) {
  14. useEffect(() => {
  15. if (index < 0) {
  16. onChange(0);
  17. } else if (tabNames.length > 0 && index >= tabNames.length) {
  18. onChange(tabNames.length - 1);
  19. }
  20. }, [tabNames, index, onChange]);
  21. const tabClass = useCallback((i: number) => {
  22. const classes = ['Tabs-element'];
  23. if (i === index) {
  24. classes.push("Tabs-active");
  25. }
  26. if (i === boldIndex) {
  27. classes.push("Tabs-bold");
  28. }
  29. return classes.join(" ");
  30. }, [index, boldIndex])
  31. return (
  32. <div className={`Tabs-container ${large ? "Tabs-large" : ""}`}>
  33. <div className="Tabs-inner">
  34. {tabNames.map((name, i) => (
  35. <div className={tabClass(i)}
  36. onClick={() => onChange(i)}
  37. >
  38. {name}
  39. </div>
  40. ))}
  41. </div>
  42. </div>
  43. );
  44. }
  45. interface PageProps {
  46. title?: string
  47. }
  48. export function Page({title, children}: PropsWithChildren<PageProps>) {
  49. useEffect(() => {
  50. window.document.title = title ? `${title} - Lucifer` : "Lucifer";
  51. }, [title]);
  52. return (
  53. <div className="Page">
  54. {children}
  55. </div>
  56. );
  57. }
  58. interface DialogProps {
  59. title: string
  60. buttons?: {
  61. text: string
  62. icon: LuciferIcon
  63. onClick?: (() => void)
  64. }[]
  65. loading?: boolean
  66. }
  67. export function Dialog({title, buttons, children}: PropsWithChildren<DialogProps>) {
  68. return (
  69. <ReactModal isOpen={true}
  70. className="Dialog-main"
  71. overlayClassName="Dialog-overlay"
  72. >
  73. <div className="Dialog-container">
  74. <div className="Dialog-header">
  75. {title}
  76. </div>
  77. {children}
  78. <div className="Dialog-footer">
  79. {buttons?.map(b => (
  80. <button key={b.text} onClick={b.onClick}>
  81. <IconBlock icon={b.icon}/>
  82. {" "}
  83. {b.text}
  84. </button>
  85. ))}
  86. </div>
  87. </div>
  88. </ReactModal>
  89. );
  90. }