Greasy Fork is available in English.

Ant Design Components Dashboard (React) (^4.0.0)

Better view for Ant Design (React)

Pada tanggal 23 Juli 2020. Lihat %(latest_version_link).

// ==UserScript==
// @name:zh-CN   Ant Design 组件菜单 (^4.0.0)
// @name         Ant Design Components Dashboard (React) (^4.0.0)
// @namespace    https://github.com/xianghongai/Ant-Design-Components-Dashboard-React
// @version      0.0.1
// @description:zh-CN  更方便的查看 Ant Design (React) 组件
// @description  Better view for Ant Design (React)
// @author       Nicholas Hsiang / 山茶树和葡萄树
// @icon         https://xinlu.ink/favicon.ico
// @match        https://ant.design/components/*
// @grant        none
// ==/UserScript==
(function () {
  "use strict";

  const bodyContainer = document.querySelector("body");

  const titleText = "Ant Design of React";
  const gridSelector = ".aside-container.menu-site";
  const columnSelector = ".ant-menu-item-group";
  const columnTitleSelector = ".ant-menu-item-group-title";
  const menuListSelector = ".ant-menu-item-group-list";
  const menuItemSelector = ".ant-menu-item-group-list .ant-menu-item";
  const helpEnable = true;
  const helpSelector = ".api-container";
  const removeSelector = gridSelector + ">li:not(.ant-menu-item-group)";

  function initialDashboard() {
    initialToggle();
    initialStyle();
    initialMenu();
    initialHelp();
    handleEvent();

    resetLayout();
  }

  let interval = null;

  function ready() {
    const originEle = document.querySelector(gridSelector);

    if (originEle) {
      clearInterval(interval);
      // Dashboard
      initialDashboard();
      // Other
    }
  }

  interval = setInterval(ready, 1000);

  // #region MENU
  /** 生成 Menu */
  function initialMenu() {
    // Wrapper
    const wrapperEle = document.createElement("section");
    wrapperEle.classList.add("hs-dashboard__wrapper", "hs-hide");

    // Header
    const headerEle = document.createElement("header");
    headerEle.classList.add("hs-dashboard__header");

    // Title
    const titleEle = document.createElement("h1");
    titleEle.classList.add("hs-dashboard__title");
    titleEle.innerText = titleText || "";

    // Title → Header
    headerEle.appendChild(titleEle);

    // Menu
    const containerEle = document.createElement("div");
    containerEle.classList.add("hs-dashboard__container");

    // 0. 移除一些不要的元素
    if (removeSelector) {
      const removeEle = document.querySelectorAll(removeSelector);
      if (removeEle) {
        removeEle.forEach((element) => {
          element.remove();
        });
      }
    }

    // 1. 先从页面上获取 DOM
    const menuEle = document.querySelector(gridSelector); // .cloneNode(true);
    menuEle.classList.add("hs-dashboard__grid"); // 追加新的样式

    // Menu → Container
    containerEle.appendChild(menuEle);

    // 2. 内部元素追加新的样式
    // 2.1 column
    const columnEle = containerEle.querySelectorAll(columnSelector);
    columnEle.forEach((element) => {
      element.classList.add("hs-dashboard__column");
    });

    // 2.2 title
    const columnTitleEle = containerEle.querySelectorAll(columnTitleSelector);
    columnTitleEle.forEach((element) => {
      element.classList.add("hs-dashboard__item-title");
    });

    // 2.3 menu list
    const menuListEle = containerEle.querySelectorAll(menuListSelector);
    menuListEle.forEach((element) => {
      element.classList.add("hs-dashboard__list");
    });

    // 2.4 menu item
    const menuItemEle = containerEle.querySelectorAll(menuItemSelector);
    menuItemEle.forEach((element) => {
      element.classList.add("hs-dashboard__item");
    });

    // header,container → wrapper
    wrapperEle.appendChild(headerEle);
    wrapperEle.appendChild(containerEle);

    // wrapper → body
    bodyContainer.appendChild(wrapperEle);
  }
  // #endregion MENU

  // #region Event
  /** 注册事件 */
  function handleEvent() {
    const wrapperEle = document.querySelector(".hs-dashboard__wrapper");

    bodyContainer.addEventListener("click", (event) => {
      const targetEle = event.target;

      const isItem = getParents(targetEle, ".hs-dashboard__item") || hasClass(targetEle, "hs-dashboard__item") || (getParents(targetEle, ".hs-dashboard__column") && getParents(targetEle, ".hs-dashboard__list"));

      const isToggle = getParents(targetEle, ".hs-dashboard__toggle-menu") || hasClass(targetEle, "hs-dashboard__toggle-menu");

      const isHelp = getParents(targetEle, ".hs-dashboard__toggle-help") || hasClass(targetEle, "hs-dashboard__toggle-help");

      if (isItem) {
        clearStyle(wrapperEle);
      } else if (isToggle) {
        wrapperEle.classList.toggle("hs-hide");
        bodyContainer.classList.toggle("hs-body-overflow_hide");
      } else if (isHelp) {
        clearStyle(wrapperEle);
        handleHelp();
      }
    });
  }

  function clearStyle(wrapperEle) {
    wrapperEle.classList.add("hs-hide");
    bodyContainer.classList.remove("hs-body-overflow_hide");
  }
  // #endregion Event

  // #region HELP
  /** 是否启用‘页面滚动至指定位置’ */
  function initialHelp() {
    if (!helpEnable) {
      const ele = document.querySelector(".hs-dashboard__toggle-help");
      ele.classList.add("hs-hide");
    }
  }

  /** 页面滚动至指定位置 */
  function handleHelp() {
    if (!helpSelector) {
      return false;
    }

    const helpEle = document.querySelector(helpSelector);
    const top = helpEle.getBoundingClientRect().top + window.pageYOffset;

    window.scrollTo({
      top,
      behavior: "smooth",
    });
  }
  // #endregion HELP

  // #region STYLE
  /** 添加样式 */
  function initialStyle() {
    const tpl = initialStyleTpl();
    const headEle = document.head || document.getElementsByTagName("head")[0];
    const styleEle = document.createElement("style");

    styleEle.type = "text/css";

    if (styleEle.styleSheet) {
      styleEle.styleSheet.cssText = tpl;
    } else {
      styleEle.appendChild(document.createTextNode(tpl));
    }

    headEle.appendChild(styleEle);
  }

  /** 样式表 */
  function initialStyleTpl() {
    return `
          .hs-hide {
            display: none !important;
          }

          .hs-body-overflow_hide {
            height: 100% !important;
            overflow: hidden !important;
          }

          /* #region toggle */
          .hs-dashboard__toggle {
            position: fixed;
            z-index: 99999;
            top: 5px;
            right: 5px;
          }

          .hs-dashboard__toggle-item {
            width: 28px;
            height: 28px;
            margin-top: 10px;
            margin-bottom: 10px;
            overflow: hidden;
            line-height: 30px !important;
            border-radius: 50%;
            border: 1px solid #ccc;
            text-align: center;
            color: #555;
            background-color: #fff;
            cursor: pointer;
            transition: all 0.2s;
          }

          .hs-dashboard__toggle-item:hover {
            border-color: #aaa;
            color: #111;
          }

          .hs-dashboard__toggle-icon {
            font-style: normal !important;
          }
          /* #endregion toggle */

          /* #region wrapper */
          .hs-dashboard__wrapper {
            position: fixed;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            z-index: 99998;
            overflow-y: auto;
            background-color: #fff;
            font-size: 16px;
          }

          .hs-dashboard__wrapper::-webkit-scrollbar {
            width: 8px;
            height: 6px;
            background: rgba(0, 0, 0, 0.1);
          }

          .hs-dashboard__wrapper::-webkit-scrollbar-thumb {
            background: rgba(0, 0, 0, 0.3);
          }

          .hs-dashboard__wrapper::-webkit-scrollbar-track {
            background: rgba(0, 0, 0, 0.1);
          }
          /* #endregion wrapper */

          .hs-dashboard__header {
            padding-top: 10px;
            text-align: center;
          }

          .hs-dashboard__title {
            margin: 0;
            padding-top: 10px;
            padding-bottom: 10px;
            font-size: 1em;
            font-weight: normal;
          }

          /* #region grid */
          .hs-dashboard__grid {
            display: flex;
            justify-content: space-evenly;
            /* justify-content: space-around; */
            margin: 0;
            padding: 0;
            list-style: none;
          }

          .hs-dashboard__column {
            padding-right: 10px;
            padding-left: 10px;
          }

          .hs-dashboard__column a {
            text-decoration: none;
          }

          .hs-dashboard__column {
            list-style: none;
          }

          .hs-dashboard__column ul {
            padding: 0;
          }

          .hs-dashboard__column li {
            list-style: none;
          }

          .hs-dashboard__column .hs-dashboard__item-title {
            display: block;
            margin-top: 0 !important;
          }

          /* #endregion grid */

          /* #region custom */
          .fixed-widgets {
            z-index: 9;
          }
          body[data-theme='dark'] .hs-dashboard__wrapper,
          body[data-theme='dark'] .hs-menu-wrapper.ant-menu {
            color: rgba(255,255,255,0.65);
            background-color: #141414;
          }

          body[data-theme='dark'] .hs-dashboard__title {
            color: rgba(255,255,255,0.65);
          }

          .hs-dashboard__column .hs-dashboard__list .hs-dashboard__item,
          .hs-dashboard__column .hs-dashboard__list .ant-menu-item {
            height: 36px;
            line-height: 36px;
          }
          /* #endregion custom */
  `;
  }
  // #endregion STYLE

  // #region TOGGLE
  /** 生成 Dashboard 开关 */
  function initialToggle() {
    const tpl = initialToggleTpl();
    const ele = document.createElement("section");
    // ele.className = 'hs-dashboard__toggle';
    // ele.setAttribute("class", "hs-dashboard__toggle");
    ele.classList.add("hs-dashboard__toggle");
    ele.innerHTML = tpl;

    // toggle → body
    bodyContainer.appendChild(ele);
  }
  /** Dashboard 开关 DOM */
  function initialToggleTpl() {
    return `
  <!-- menu -->
  <div class="hs-dashboard__toggle-item hs-dashboard__toggle-menu">
    <i class="hs-dashboard__toggle-icon">
      <svg
        viewBox="64 64 896 896"
        focusable="false"
        data-icon="appstore"
        width="1em"
        height="1em"
        fill="currentColor"
        aria-hidden="true"
      >
        <path
          d="M464 144H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H212V212h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H612V212h200v200zM464 544H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H212V612h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H612V612h200v200z"
        ></path>
      </svg>
    </i>
  </div>
  <!-- api -->
  <div class="hs-dashboard__toggle-item hs-dashboard__toggle-help">
    <i class="hs-dashboard__toggle-icon">
      <svg
        viewBox="64 64 896 896"
        focusable="false"
        class=""
        data-icon="bulb"
        width="1em"
        height="1em"
        fill="currentColor"
        aria-hidden="true"
      >
        <path
          d="M632 888H392c-4.4 0-8 3.6-8 8v32c0 17.7 14.3 32 32 32h192c17.7 0 32-14.3 32-32v-32c0-4.4-3.6-8-8-8zM512 64c-181.1 0-328 146.9-328 328 0 121.4 66 227.4 164 284.1V792c0 17.7 14.3 32 32 32h264c17.7 0 32-14.3 32-32V676.1c98-56.7 164-162.7 164-284.1 0-181.1-146.9-328-328-328zm127.9 549.8L604 634.6V752H420V634.6l-35.9-20.8C305.4 568.3 256 484.5 256 392c0-141.4 114.6-256 256-256s256 114.6 256 256c0 92.5-49.4 176.3-128.1 221.8z"
        ></path>
      </svg>
    </i>
  </div>
`;
  }
  // #endregion TOGGLE

  // #region COMMON
  function hasClass(el, className) {
    if (el.classList) {
      return el.classList.contains(className);
    } else {
      return !!el.className.match(new RegExp("(\\s|^)" + className + "(\\s|$)"));
    }
  }

  function getParents(elem, selector) {
    // Element.matches() polyfill
    if (!Element.prototype.matches) {
      Element.prototype.matches =
        Element.prototype.matchesSelector ||
        Element.prototype.mozMatchesSelector ||
        Element.prototype.msMatchesSelector ||
        Element.prototype.oMatchesSelector ||
        Element.prototype.webkitMatchesSelector ||
        function (s) {
          var matches = (this.document || this.ownerDocument).querySelectorAll(s),
            i = matches.length;
          while (--i >= 0 && matches.item(i) !== this) {}
          return i > -1;
        };
    }

    // Get the closest matching element
    for (; elem && elem !== document; elem = elem.parentNode) {
      if (elem.matches(selector)) return elem;
    }
    return null;
  }
  // #endregion

  function resetLayout() {
    const pageSider = document.querySelector(".main-wrapper>.ant-row>.main-menu");
    const pageContainer = document.querySelector(".main-wrapper>.ant-row>.ant-col+.ant-col");

    pageSider.classList.add("hs-hide");
    pageContainer.classList.remove("ant-col-md-18", "ant-col-lg-18", "ant-col-xl-19", "ant-col-xxl-20");
    pageContainer.classList.add("ant-col-md-24", "ant-col-lg-24", "ant-col-xl-24", "ant-col-xxl-24");
  }
})();