Browse Source

支持通过 Koyeb 部署

luolongfei 3 years ago
parent
commit
ba192af901
83 changed files with 29032 additions and 47 deletions
  1. 4 1
      .env.example
  2. 6 0
      CHANGELOG.md
  3. 29 0
      Dockerfile.koyeb
  4. 15 3
      README.md
  5. 1 1
      app/Console/FreeNom.php
  6. 7 0
      app/Console/Upgrade.php
  7. 26 24
      app/helpers.php
  8. 3 4
      docker-entrypoint.sh
  9. BIN
      koyeb/favicon.ico
  10. 34 0
      koyeb/nginx.template.conf
  11. 57 0
      koyeb/startup.sh
  12. 5 0
      koyeb/web/composer.json
  13. 79 0
      koyeb/web/composer.lock
  14. 13559 0
      koyeb/web/css/mdui.css
  15. 0 0
      koyeb/web/css/mdui.css.map
  16. 4 0
      koyeb/web/css/mdui.min.css
  17. 0 0
      koyeb/web/css/mdui.min.css.map
  18. 201 0
      koyeb/web/fonts/roboto/LICENSE.txt
  19. BIN
      koyeb/web/fonts/roboto/Roboto-Black.woff
  20. BIN
      koyeb/web/fonts/roboto/Roboto-Black.woff2
  21. BIN
      koyeb/web/fonts/roboto/Roboto-BlackItalic.woff
  22. BIN
      koyeb/web/fonts/roboto/Roboto-BlackItalic.woff2
  23. BIN
      koyeb/web/fonts/roboto/Roboto-Bold.woff
  24. BIN
      koyeb/web/fonts/roboto/Roboto-Bold.woff2
  25. BIN
      koyeb/web/fonts/roboto/Roboto-BoldItalic.woff
  26. BIN
      koyeb/web/fonts/roboto/Roboto-BoldItalic.woff2
  27. BIN
      koyeb/web/fonts/roboto/Roboto-Light.woff
  28. BIN
      koyeb/web/fonts/roboto/Roboto-Light.woff2
  29. BIN
      koyeb/web/fonts/roboto/Roboto-LightItalic.woff
  30. BIN
      koyeb/web/fonts/roboto/Roboto-LightItalic.woff2
  31. BIN
      koyeb/web/fonts/roboto/Roboto-Medium.woff
  32. BIN
      koyeb/web/fonts/roboto/Roboto-Medium.woff2
  33. BIN
      koyeb/web/fonts/roboto/Roboto-MediumItalic.woff
  34. BIN
      koyeb/web/fonts/roboto/Roboto-MediumItalic.woff2
  35. BIN
      koyeb/web/fonts/roboto/Roboto-Regular.woff
  36. BIN
      koyeb/web/fonts/roboto/Roboto-Regular.woff2
  37. BIN
      koyeb/web/fonts/roboto/Roboto-RegularItalic.woff
  38. BIN
      koyeb/web/fonts/roboto/Roboto-RegularItalic.woff2
  39. BIN
      koyeb/web/fonts/roboto/Roboto-Thin.woff
  40. BIN
      koyeb/web/fonts/roboto/Roboto-Thin.woff2
  41. BIN
      koyeb/web/fonts/roboto/Roboto-ThinItalic.woff
  42. BIN
      koyeb/web/fonts/roboto/Roboto-ThinItalic.woff2
  43. 393 0
      koyeb/web/icons/material-icons/LICENSE.txt
  44. 0 0
      koyeb/web/icons/material-icons/MaterialIcons-Regular.ijmap
  45. BIN
      koyeb/web/icons/material-icons/MaterialIcons-Regular.woff
  46. BIN
      koyeb/web/icons/material-icons/MaterialIcons-Regular.woff2
  47. BIN
      koyeb/web/images/logo_bear.png
  48. 349 0
      koyeb/web/index.php
  49. 6 0
      koyeb/web/js/clipboard.min.js
  50. 5976 0
      koyeb/web/js/mdui.esm.js
  51. 0 0
      koyeb/web/js/mdui.esm.js.map
  52. 6474 0
      koyeb/web/js/mdui.js
  53. 0 0
      koyeb/web/js/mdui.js.map
  54. 5 0
      koyeb/web/js/mdui.min.js
  55. 0 0
      koyeb/web/js/mdui.min.js.map
  56. 7 0
      koyeb/web/vendor/autoload.php
  57. 572 0
      koyeb/web/vendor/composer/ClassLoader.php
  58. 337 0
      koyeb/web/vendor/composer/InstalledVersions.php
  59. 21 0
      koyeb/web/vendor/composer/LICENSE
  60. 10 0
      koyeb/web/vendor/composer/autoload_classmap.php
  61. 9 0
      koyeb/web/vendor/composer/autoload_namespaces.php
  62. 10 0
      koyeb/web/vendor/composer/autoload_psr4.php
  63. 57 0
      koyeb/web/vendor/composer/autoload_real.php
  64. 36 0
      koyeb/web/vendor/composer/autoload_static.php
  65. 69 0
      koyeb/web/vendor/composer/installed.json
  66. 32 0
      koyeb/web/vendor/composer/installed.php
  67. 26 0
      koyeb/web/vendor/composer/platform_check.php
  68. 2 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/.gitignore
  69. 19 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/LICENSE
  70. 109 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/README.md
  71. 157 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/AnsiToHtmlConverter.php
  72. 48 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Bridge/Twig/AnsiExtension.php
  73. 59 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Tests/AnsiToHtmlConverterTest.php
  74. 45 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Theme/SolarizedTheme.php
  75. 45 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Theme/SolarizedXTermTheme.php
  76. 52 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Theme/Theme.php
  77. 32 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/composer.json
  78. 19 0
      koyeb/web/vendor/sensiolabs/ansi-to-html/phpunit.xml.dist
  79. 14 6
      libs/Log.php
  80. 8 2
      libs/MessageServices/WeChat.php
  81. 2 3
      resources/lang/en.php
  82. 2 3
      resources/lang/zh.php
  83. BIN
      resources/screenshot/koyeb01.png

+ 4 - 1
.env.example

@@ -12,7 +12,7 @@
 #####################################################################
 
 # .env 文件版本
-ENV_FILE_VERSION='v2.5'
+ENV_FILE_VERSION='v2.6'
 
 ######################  账户配置 Account config  #########################
 # Freenom 账户 Freenom Account
@@ -138,3 +138,6 @@ CUSTOM_LANGUAGE=zh
 
 # 送信时是否显示服务器信息 1:显示 0:不显示 Whether to display server information when sending messages 1: Display 0: Do not display
 SHOW_SERVER_INFO=0
+
+# 是否给敏感信息打码 1:启用 0:不启用 Whether to enable the obfuscation of sensitive information 1: Enabled 0: Not enabled
+MOSAIC_SENSITIVE_INFO=0

+ 6 - 0
CHANGELOG.md

@@ -2,6 +2,12 @@
 
 此处包含了自脚本发布以来的所有更新日志。以前的日志只记录了比较大的变更,以后的日志会尽可能详尽一些。
 
+#### [v0.5.1](https://github.com/luolongfei/freenom/releases/tag/v0.5.1) - 2022-08-27
+
+- 支持一键部署至 Koyeb、Heroku 等平台,虽然 Heroku 马上要收费了,但 Koyeb 依然免费
+- 优化在各种环境下的目录读写权限判断
+- 支持给日志或者命令行输出内容中的敏感信息打马赛克,默认不启用
+
 #### [v0.5](https://github.com/luolongfei/freenom/releases/tag/v0.5) - 2022-05-15
 
 - 增加支持 华为云函数、Railway 等部署方式

+ 29 - 0
Dockerfile.koyeb

@@ -0,0 +1,29 @@
+FROM php:8.1.9-fpm-alpine3.16
+
+LABEL author="mybsdc <[email protected]>" \
+    maintainer="luolongfei <[email protected]>"
+
+ENV TZ Asia/Shanghai
+ENV IS_KOYEB 1
+
+WORKDIR /app
+
+COPY . ./
+
+COPY ./koyeb/nginx.template.conf ./
+COPY ./koyeb/web ./web/
+
+RUN set -eux \
+    && apk update \
+    && apk add --no-cache tzdata bash nginx gettext \
+    && mkdir -p /app/logs \
+    && chmod -Rf 666 /app/logs
+
+COPY ./koyeb/startup.sh /
+RUN chmod +x /startup.sh
+
+EXPOSE 80 443 2019
+
+# https://www.koyeb.com/docs/deploy-to-koyeb-button
+# https://www.koyeb.com/docs/quickstart/deploy-a-docker-application
+CMD ["/bin/bash", "-c", "/startup.sh"]

+ 15 - 3
README.md

@@ -30,6 +30,8 @@ Documentation: [English version](https://github.com/luolongfei/freenom/blob/main
 
 [🚈 通过 Railway 部署](#-通过-Railway-部署)
 
+[📦 通过 Koyeb 部署](#-通过-Koyeb-部署)(推荐没有自己服务器的用户使用此方案,一键部署)
+
 [☁ 通过 各种云函数 部署](#-通过各种云函数部署)
 
 [🚧 直接拉取源码部署](#-直接拉取源码部署)
@@ -79,7 +81,7 @@ Thanks for non-commercial open source development authorization by JetBrains.
 
 无论是续期成败或者程序执行出错,都会收到脚本发出的通知。如果是续期成败相关的通知,通知会包括未续期域名的到期天数等内容。*此处展示的是通知邮件的内容。*
 
-<a href="https://s4.ax1x.com/2022/02/26/bZr7WQ.png"><img src="https://s4.ax1x.com/2022/02/26/bZr7WQ.png" alt="邮件示例" border="0" width="670" height="540" /></a>
+<a href="https://s4.ax1x.com/2022/02/26/bZr7WQ.png"><img src="https://s4.ax1x.com/2022/02/26/bZr7WQ.png" alt="邮件示例" border="0" width="95%" height="100%" /></a>
 
 ### 🎁 事前准备
 
@@ -410,8 +412,6 @@ systemctl restart docker
 
 ### 🧊 通过 Heroku 部署
 
-~~*推荐没有自己服务器的用户使用此方案部署。此方案完全免费。*~~
-
 **Heroku 将于 2022-11-28 停止提供免费服务,所以,忘掉本文吧。官方通告:[https://blog.heroku.com/next-chapter](https://blog.heroku.com/next-chapter)**
 
 有关 【通过 Heroku 部署】 的具体操作步骤请参考 [此处](https://github.com/luolongfei/freenom/wiki/%E9%80%9A%E8%BF%87-Heroku-%E9%83%A8%E7%BD%B2)
@@ -427,6 +427,18 @@ systemctl restart docker
 
 ***
 
+### 📦 通过 Koyeb 部署
+
+*推荐没有自己服务器的用户使用此方案部署。此方案完全免费。*
+
+有关 【通过 Koyeb 部署】 的具体操作步骤请参考 [此处](https://github.com/luolongfei/freenom/wiki/%E9%80%9A%E8%BF%87-Koyeb-%E9%83%A8%E7%BD%B2)
+
+**在看完上行文档的具体内容,并且你确定你行后**,便可点击下方按钮,尝试一键部署:
+
+[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?type=docker&name=freenom&ports=80;http;/&env[FF_TOKEN]=20190214&env[SHOW_SERVER_INFO]=1&env[MOSAIC_SENSITIVE_INFO]=1&env[FREENOM_USERNAME]=&env[FREENOM_PASSWORD]=&env[MULTIPLE_ACCOUNTS]=&env[TELEGRAM_CHAT_ID]=&env[TELEGRAM_BOT_TOKEN]=&env[TELEGRAM_BOT_ENABLE]=0&image=docker.io/luolongfei/freenom:koyeb)
+
+***
+
 ### ☁ 通过各种云函数部署
 
 所有云函数使用的是同一个压缩包,已做兼容处理,下载地址:

+ 1 - 1
app/Console/FreeNom.php

@@ -19,7 +19,7 @@ use Luolongfei\Libs\Message;
 
 class FreeNom extends Base
 {
-    const VERSION = 'v0.5';
+    const VERSION = 'v0.5.1';
 
     const TIMEOUT = 33;
 

+ 7 - 0
app/Console/Upgrade.php

@@ -210,6 +210,13 @@ class Upgrade extends Base
     public function handle()
     {
         try {
+            // 检查 Data 目录写权限
+            if (!is_writable(DATA_PATH)) {
+                system_log(lang('100135'));
+
+                return true;
+            }
+
             if (!$this->needToUpgrade()) {
                 return true;
             }

+ 26 - 24
app/helpers.php

@@ -65,30 +65,16 @@ if (!function_exists('system_log')) {
     function system_log($content, array $response = [], $fileName = '')
     {
         try {
-            # 云函数只有 /tmp 目录可写
-            $path = IS_SCF ? '/tmp/' : sprintf('%s/logs/%s/', ROOT_PATH, date('Y-m'));
-            $file = $path . ($fileName ?: date('d')) . '.log';
-
-            if (!is_dir($path)) {
-                mkdir($path, 0777, true);
-                chmod($path, 0777);
-            }
-
-            $handle = fopen($file, 'a'); // 追加而非覆盖
-
-            if (!filesize($file)) {
-                chmod($file, 0666);
-            }
-
             $msg = sprintf(
                 "[%s] %s %s\n",
                 date('Y-m-d H:i:s'),
                 is_string($content) ? $content : json_encode($content),
                 $response ? json_encode($response, JSON_UNESCAPED_UNICODE) : '');
 
-            // 在 Github Actions 上运行,过滤敏感信息
-            if (env('ON_GITHUB_ACTIONS')) {
-                $msg = preg_replace_callback('/(?P<secret>[\w-.]{1,4}?)(?=@[\w-.]+)/i', function ($m) {
+            // 过滤敏感信息
+            if ((int)env('MOSAIC_SENSITIVE_INFO') === 1) {
+                // 在 php 7.3 之前,连字符“-”在中括号中随便放,但在之后,只能放在开头或结尾或者转义后才能随便放
+                $msg = preg_replace_callback('/(?P<secret>[\w.-]{1,3}?)(?=@[\w.-]+)/ui', function ($m) {
                     return str_ireplace($m['secret'], str_repeat('*', strlen($m['secret'])), $m['secret']);
                 }, $msg);
             }
@@ -100,8 +86,26 @@ if (!function_exists('system_log')) {
             // 干掉着色标签
             $msg = strip_tags($msg); // 不完整或者破损标签将导致更多的数据被删除
 
-            fwrite($handle, $msg);
-            fclose($handle);
+            // 写入日志文件
+            if (is_writable(ROOT_PATH)) {
+                $path = sprintf('%s/logs/%s/', ROOT_PATH, date('Y-m'));
+                $file = $path . ($fileName ?: date('d')) . '.log';
+
+                if (!is_dir($path)) {
+                    mkdir($path, 0666, true); // 0666 所有用户可读写
+                }
+
+                $handle = fopen($file, 'a'); // 追加而非覆盖
+
+                if ($handle !== false) {
+                    if (!filesize($file)) {
+                        chmod($file, 0666);
+                    }
+
+                    fwrite($handle, $msg);
+                    fclose($handle);
+                }
+            }
 
             flush();
         } catch (\Exception $e) {
@@ -238,11 +242,9 @@ if (!function_exists('system_check')) {
             throw new LlfException(34520006, ['7.3', PHP_VERSION]);
         }
 
-        // 如果是在 云函数 或 Heroku 部署,则不需要检查这几项
-        if (IS_SCF || (int)env('IS_HEROKU') === 1) {
+        // 特殊环境无需检查这几项
+        if (IS_SCF || !is_writable(ROOT_PATH) || (int)env('IS_KOYEB') === 1 || (int)env('IS_HEROKU') === 1) {
             system_log(lang('100009'));
-            system_log(lang('100010'));
-            system_log(lang('100011'));
         } else {
             if (!function_exists('putenv')) {
                 throw new LlfException(34520005);

+ 3 - 4
docker-entrypoint.sh

@@ -15,15 +15,14 @@ plain='\033[0m'
 
 # 生成配置文件
 if [ ! -f /conf/.env ]; then
-    cp /app/.env.example /conf/.env
-    echo -e "[${green}Info${plain}] 已生成 .env 文件,请将 .env 文件中的配置项改为你自己的,然后重启容器(如果你是在第三方 Docker 环境中使用容器,例如 railway/heroku 等平台,可忽略本条提醒)"
+    cp /app/.env.example /conf/.env && echo -e "[${green}Info${plain}] 已生成 .env 文件,请将 .env 文件中的配置项改为你自己的,然后重启容器,如果当前环境非普通 VPS,可忽略此提示" || echo -e "[${yellow}Warn${plain}] 未能正常生成 .env 文件"
 fi
 if [ ! -f /app/.env ]; then
-    ln -s /conf/.env /app/.env
+    ln -s /conf/.env /app/.env || echo -e "[${yellow}Warn${plain}] 未能正常创建 .env 文件链接"
 fi
 
 # PHP 命令
-PHP_COMMAND='php /app/run > /app/logs/freenom_cron.log 2>&1'
+PHP_COMMAND='/usr/local/bin/php /app/run > /app/logs/freenom_cron.log 2>&1'
 
 # 指定脚本执行时间
 if [ -z "${RUN_AT}" ]; then

BIN
koyeb/favicon.ico


+ 34 - 0
koyeb/nginx.template.conf

@@ -0,0 +1,34 @@
+worker_processes auto;
+
+error_log stderr;
+pid /var/run/nginx.pid;
+
+events {
+  worker_connections 1024;
+}
+
+http {
+  include /etc/nginx/mime.types;
+  access_log /dev/stdout;
+  server_tokens off;
+
+  server {
+        listen 80;
+
+        root /app/web;
+
+        location / {
+            index index.php index.html index.htm;
+        }
+
+        location ~ \.php$ {
+          try_files $uri =404;
+          fastcgi_split_path_info ^(.+?\.php)(/.*)$;
+          fastcgi_pass 127.0.0.1:9000;
+          fastcgi_index index.php;
+          include /etc/nginx/fastcgi_params;
+          fastcgi_param SCRIPT_FILENAME /app/web/$fastcgi_script_name;
+          fastcgi_param PATH_INFO $fastcgi_path_info;
+        }
+    }
+}

+ 57 - 0
koyeb/startup.sh

@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+
+#===================================================================#
+#   Author: luolongfei <[email protected]>                         #
+#   Intro: https://github.com/luolongfei/freenom                    #
+#===================================================================#
+
+set -e
+
+# 自定义颜色变量
+red='\033[0;31m'
+green='\033[0;32m'
+yellow='\033[0;33m'
+plain='\033[0m'
+
+echo -e "[${green}Info${plain}] 项目地址:https://github.com/luolongfei/freenom"
+echo -e "[${green}Info${plain}] 洛阳亲友如相问,一片冰心在玉壶。 by luolongfei"
+
+# PHP 命令
+PHP_COMMAND='/usr/local/bin/php /app/run > /app/logs/freenom_cron.log 2>&1'
+
+# 指定脚本执行时间
+if [ -z "${RUN_AT}" ]; then
+    minute=$( shuf -i 0-59 -n 1 )
+    hour=$( shuf -i 6-23 -n 1 )
+    CRON_COMMAND="${minute} ${hour} * * * ${PHP_COMMAND}"
+    echo -e "[${green}Info${plain}] 已自动指定执行时间,续期任务将在北京时间每天 「${hour}:${minute}」 执行"
+    echo -e "[${green}Info${plain}] 在没有手动指定 RUN_AT 环境变量的情况下,每次重建容器,程序都会重新在 06 ~ 23 点全时段中自动随机指定一个执行时间,目的是防止很多人在同一个时间点执行任务导致 Freenom 无法稳定提供服务"
+else
+    if [[ "${RUN_AT}" =~ ^([01][0-9]|2[0-3]|[0-9]):([0-5][0-9]|[0-9])$ ]]; then
+        minute=$( echo ${RUN_AT} | egrep -o '([0-5][0-9]|[0-9])$' )
+        hour=$( echo ${RUN_AT} | egrep -o '^([01][0-9]|2[0-3]|[0-9])' )
+        CRON_COMMAND="${minute} ${hour} * * * ${PHP_COMMAND}"
+        echo -e "[${green}Info${plain}] 你已指定执行时间,续期任务将在北京时间每天 「${hour}:${minute}」 执行"
+    elif [ "$(php /app/run -c=Cron -m=verify --cron_exp="${RUN_AT}")" -eq 1 ]; then
+        CRON_COMMAND="${RUN_AT} ${PHP_COMMAND}"
+        echo -e "[${green}Info${plain}] 你自定义的 Cron 表达式为「${RUN_AT}」,已通过正则验证"
+    else
+        echo -e "[${red}Error${plain}] RUN_AT 的值无效"
+        echo -e "${yellow}请输入一个有效的时间指令,其值可以为时分格式,如:11:24,也可以为 Cron 表达式,如:'24 11 * * *',甚至可以不输入,让程序自动生成,推荐采用自动生成的方式,不建议手动指定此环境变量"
+        exit 1
+    fi
+fi
+
+# 添加计划任务
+sed -i '/freenom_cron/'d /etc/crontabs/root
+echo -e "${CRON_COMMAND}" >> /etc/crontabs/root
+echo -e "[${green}Info${plain}] 计划任务:${CRON_COMMAND}"
+
+# 启动 Cron
+/usr/sbin/crond
+
+# nginx 配置
+cp /app/nginx.template.conf /app/nginx.conf
+
+# 启动 php-fpm 与 nginx
+php-fpm -D -R; nginx -c /app/nginx.conf -g 'daemon off;'

+ 5 - 0
koyeb/web/composer.json

@@ -0,0 +1,5 @@
+{
+    "require": {
+        "sensiolabs/ansi-to-html": "^1.2"
+    }
+}

+ 79 - 0
koyeb/web/composer.lock

@@ -0,0 +1,79 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "a56995c0c0eb50fce072f08da4de1561",
+    "packages": [
+        {
+            "name": "sensiolabs/ansi-to-html",
+            "version": "v1.2.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sensiolabs/ansi-to-html.git",
+                "reference": "94a3145aae4733ff933c8910263ef56d1ae317a9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sensiolabs/ansi-to-html/zipball/94a3145aae4733ff933c8910263ef56d1ae317a9",
+                "reference": "94a3145aae4733ff933c8910263ef56d1ae317a9",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.2.5"
+            },
+            "conflict": {
+                "twig/twig": "< 2.4.0"
+            },
+            "require-dev": {
+                "twig/twig": "^2.4 || ^3.0"
+            },
+            "suggest": {
+                "twig/twig": "Provides nice templating features"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.2-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "SensioLabs\\AnsiConverter\\": "SensioLabs/AnsiConverter"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "[email protected]"
+                }
+            ],
+            "description": "A library to convert a text with ANSI codes to HTML",
+            "support": {
+                "issues": "https://github.com/sensiolabs/ansi-to-html/issues",
+                "source": "https://github.com/sensiolabs/ansi-to-html/tree/v1.2.1"
+            },
+            "time": "2020-10-06T05:48:55+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": [],
+    "platform-dev": [],
+    "plugin-api-version": "2.1.0"
+}

+ 13559 - 0
koyeb/web/css/mdui.css

@@ -0,0 +1,13559 @@
+/*!
+ * mdui 1.0.2 (https://mdui.org)
+ * Copyright 2016-2021 zdhxiong
+ * Licensed under MIT
+ *//*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
+
+/* Document
+   ========================================================================== */
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+
+html {
+  line-height: 1.15; /* 1 */
+  -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/* Sections
+   ========================================================================== */
+
+/**
+ * Remove the margin in all browsers.
+ */
+
+body {
+  margin: 0;
+}
+
+/**
+ * Render the `main` element consistently in IE.
+ */
+
+main {
+  display: block;
+}
+
+/**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+/* Grouping content
+   ========================================================================== */
+
+/**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+hr {
+  -webkit-box-sizing: content-box;
+          box-sizing: content-box; /* 1 */
+  height: 0; /* 1 */
+  overflow: visible; /* 2 */
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+pre {
+  font-family: monospace, monospace; /* 1 */
+  font-size: 1em; /* 2 */
+}
+
+/* Text-level semantics
+   ========================================================================== */
+
+/**
+ * Remove the gray background on active links in IE 10.
+ */
+
+a {
+  background-color: transparent;
+}
+
+/**
+ * 1. Remove the bottom border in Chrome 57-
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+abbr[title] {
+  border-bottom: none; /* 1 */
+  text-decoration: underline; /* 2 */
+  -webkit-text-decoration: underline dotted;
+          text-decoration: underline dotted; /* 2 */
+}
+
+/**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+b,
+strong {
+  font-weight: bolder;
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+code,
+kbd,
+samp {
+  font-family: monospace, monospace; /* 1 */
+  font-size: 1em; /* 2 */
+}
+
+/**
+ * Add the correct font size in all browsers.
+ */
+
+small {
+  font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+sup {
+  top: -0.5em;
+}
+
+/* Embedded content
+   ========================================================================== */
+
+/**
+ * Remove the border on images inside links in IE 10.
+ */
+
+img {
+  border-style: none;
+}
+
+/* Forms
+   ========================================================================== */
+
+/**
+ * 1. Change the font styles in all browsers.
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  font-family: inherit; /* 1 */
+  font-size: 100%; /* 1 */
+  line-height: 1.15; /* 1 */
+  margin: 0; /* 2 */
+}
+
+/**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+button,
+input { /* 1 */
+  overflow: visible;
+}
+
+/**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+button,
+select { /* 1 */
+  text-transform: none;
+}
+
+/**
+ * Correct the inability to style clickable types in iOS and Safari.
+ */
+
+button,
+[type="button"],
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button;
+}
+
+/**
+ * Remove the inner border and padding in Firefox.
+ */
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+
+/**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+
+/**
+ * Correct the padding in Firefox.
+ */
+
+fieldset {
+  padding: 0.35em 0.75em 0.625em;
+}
+
+/**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ *    `fieldset` elements in all browsers.
+ */
+
+legend {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box; /* 1 */
+  color: inherit; /* 2 */
+  display: table; /* 1 */
+  max-width: 100%; /* 1 */
+  padding: 0; /* 3 */
+  white-space: normal; /* 1 */
+}
+
+/**
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+progress {
+  vertical-align: baseline;
+}
+
+/**
+ * Remove the default vertical scrollbar in IE 10+.
+ */
+
+textarea {
+  overflow: auto;
+}
+
+/**
+ * 1. Add the correct box sizing in IE 10.
+ * 2. Remove the padding in IE 10.
+ */
+
+[type="checkbox"],
+[type="radio"] {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box; /* 1 */
+  padding: 0; /* 2 */
+}
+
+/**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+/**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+[type="search"] {
+  -webkit-appearance: textfield; /* 1 */
+  outline-offset: -2px; /* 2 */
+}
+
+/**
+ * Remove the inner padding in Chrome and Safari on macOS.
+ */
+
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+/**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+::-webkit-file-upload-button {
+  -webkit-appearance: button; /* 1 */
+  font: inherit; /* 2 */
+}
+
+/* Interactive
+   ========================================================================== */
+
+/*
+ * Add the correct display in Edge, IE 10+, and Firefox.
+ */
+
+details {
+  display: block;
+}
+
+/*
+ * Add the correct display in all browsers.
+ */
+
+summary {
+  display: list-item;
+}
+
+/* Misc
+   ========================================================================== */
+
+/**
+ * Add the correct display in IE 10+.
+ */
+
+template {
+  display: none;
+}
+
+/**
+ * Add the correct display in IE 10.
+ */
+
+[hidden] {
+  display: none;
+}
+
+/**
+ * =============================================================================
+ * ************   公共样式   ************
+ * =============================================================================
+ */
+* {
+  -webkit-tap-highlight-color: transparent;
+}
+body {
+  color: rgba(0, 0, 0, 0.87);
+  font-size: 14px;
+  font-family: Roboto, Noto, Helvetica, Arial, sans-serif;
+  background-color: #fff;
+}
+@media (min-width: 600px) {
+  body {
+    font-size: 14.5px;
+  }
+}
+@media (min-width: 1024px) {
+  body {
+    font-size: 15px;
+  }
+}
+body *::-webkit-scrollbar {
+  width: 5px;
+  height: 5px;
+  background: transparent;
+}
+@media (min-width: 1024px) {
+  body *::-webkit-scrollbar {
+    width: 8px;
+    height: 8px;
+  }
+}
+body *::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+}
+/* 锁定屏幕 */
+body.mdui-locked {
+  overflow: hidden;
+}
+/* 遮罩层 */
+.mdui-overlay {
+  position: fixed;
+  top: -5000px;
+  right: -5000px;
+  bottom: -5000px;
+  left: -5000px;
+  z-index: 2000;
+  background: rgba(0, 0, 0, 0.4);
+  -webkit-backface-visibility: hidden;
+          backface-visibility: hidden;
+  visibility: hidden;
+  opacity: 0;
+  -webkit-transition-duration: 0.3s;
+          transition-duration: 0.3s;
+  -webkit-transition-property: opacity, visibility;
+  transition-property: opacity, visibility;
+  will-change: opacity;
+}
+/* 显示遮罩层 */
+.mdui-overlay-show {
+  visibility: visible;
+  opacity: 1;
+}
+/* 取消 transition 过渡效果 */
+.mdui-no-transition {
+  -webkit-transition-property: none !important;
+  transition-property: none !important;
+}
+/**
+ * =============================================================================
+ * ************   Global dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark {
+  color: #fff;
+  background-color: #303030;
+}
+.mdui-theme-layout-dark *::-webkit-scrollbar {
+  width: 5px;
+  height: 5px;
+  background: transparent;
+}
+@media (min-width: 1024px) {
+  .mdui-theme-layout-dark *::-webkit-scrollbar {
+    width: 8px;
+    height: 8px;
+  }
+}
+.mdui-theme-layout-dark *::-webkit-scrollbar-thumb {
+  background: rgba(255, 255, 255, 0.3);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto {
+    color: #fff;
+    background-color: #303030;
+  }
+  .mdui-theme-layout-auto *::-webkit-scrollbar {
+    width: 5px;
+    height: 5px;
+    background: transparent;
+  }
+  .mdui-theme-layout-auto *::-webkit-scrollbar-thumb {
+    background: rgba(255, 255, 255, 0.3);
+  }
+}
+@media (prefers-color-scheme: dark) and (min-width: 1024px) {
+  .mdui-theme-layout-auto *::-webkit-scrollbar {
+    width: 8px;
+    height: 8px;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Color 颜色   ************
+ * =============================================================================
+ */
+/**
+ * .mdui-theme-primary-[color] .mdui-color-theme
+ * .mdui-theme-primary-[color] .mdui-color-theme-[degree]
+ */
+.mdui-theme-primary-amber .mdui-color-theme {
+  background-color: #FFC107 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-50 {
+  background-color: #FFF8E1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-100 {
+  background-color: #FFECB3 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-200 {
+  background-color: #FFE082 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-300 {
+  background-color: #FFD54F !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-400 {
+  background-color: #FFCA28 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-500 {
+  background-color: #FFC107 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-600 {
+  background-color: #FFB300 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-700 {
+  background-color: #FFA000 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-800 {
+  background-color: #FF8F00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-amber .mdui-color-theme-900 {
+  background-color: #FF6F00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme {
+  background-color: #2196F3 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-50 {
+  background-color: #E3F2FD !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-100 {
+  background-color: #BBDEFB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-200 {
+  background-color: #90CAF9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-300 {
+  background-color: #64B5F6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-400 {
+  background-color: #42A5F5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-500 {
+  background-color: #2196F3 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-600 {
+  background-color: #1E88E5 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-700 {
+  background-color: #1976D2 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-800 {
+  background-color: #1565C0 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue .mdui-color-theme-900 {
+  background-color: #0D47A1 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme {
+  background-color: #607D8B !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-50 {
+  background-color: #ECEFF1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-100 {
+  background-color: #CFD8DC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-200 {
+  background-color: #B0BEC5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-300 {
+  background-color: #90A4AE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-400 {
+  background-color: #78909C !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-500 {
+  background-color: #607D8B !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-600 {
+  background-color: #546E7A !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-700 {
+  background-color: #455A64 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-800 {
+  background-color: #37474F !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-blue-grey .mdui-color-theme-900 {
+  background-color: #263238 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme {
+  background-color: #795548 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-50 {
+  background-color: #EFEBE9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-100 {
+  background-color: #D7CCC8 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-200 {
+  background-color: #BCAAA4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-300 {
+  background-color: #A1887F !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-400 {
+  background-color: #8D6E63 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-500 {
+  background-color: #795548 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-600 {
+  background-color: #6D4C41 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-700 {
+  background-color: #5D4037 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-800 {
+  background-color: #4E342E !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-brown .mdui-color-theme-900 {
+  background-color: #3E2723 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme {
+  background-color: #00BCD4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-50 {
+  background-color: #E0F7FA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-100 {
+  background-color: #B2EBF2 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-200 {
+  background-color: #80DEEA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-300 {
+  background-color: #4DD0E1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-400 {
+  background-color: #26C6DA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-500 {
+  background-color: #00BCD4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-600 {
+  background-color: #00ACC1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-700 {
+  background-color: #0097A7 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-800 {
+  background-color: #00838F !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-cyan .mdui-color-theme-900 {
+  background-color: #006064 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme {
+  background-color: #FF5722 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-50 {
+  background-color: #FBE9E7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-100 {
+  background-color: #FFCCBC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-200 {
+  background-color: #FFAB91 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-300 {
+  background-color: #FF8A65 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-400 {
+  background-color: #FF7043 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-500 {
+  background-color: #FF5722 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-600 {
+  background-color: #F4511E !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-700 {
+  background-color: #E64A19 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-800 {
+  background-color: #D84315 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-orange .mdui-color-theme-900 {
+  background-color: #BF360C !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme {
+  background-color: #673AB7 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-50 {
+  background-color: #EDE7F6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-100 {
+  background-color: #D1C4E9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-200 {
+  background-color: #B39DDB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-300 {
+  background-color: #9575CD !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-400 {
+  background-color: #7E57C2 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-500 {
+  background-color: #673AB7 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-600 {
+  background-color: #5E35B1 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-700 {
+  background-color: #512DA8 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-800 {
+  background-color: #4527A0 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-deep-purple .mdui-color-theme-900 {
+  background-color: #311B92 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-green .mdui-color-theme {
+  background-color: #4CAF50 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-50 {
+  background-color: #E8F5E9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-100 {
+  background-color: #C8E6C9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-200 {
+  background-color: #A5D6A7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-300 {
+  background-color: #81C784 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-400 {
+  background-color: #66BB6A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-500 {
+  background-color: #4CAF50 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-600 {
+  background-color: #43A047 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-700 {
+  background-color: #388E3C !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-800 {
+  background-color: #2E7D32 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-green .mdui-color-theme-900 {
+  background-color: #1B5E20 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme {
+  background-color: #9E9E9E !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-50 {
+  background-color: #FAFAFA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-100 {
+  background-color: #F5F5F5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-200 {
+  background-color: #EEEEEE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-300 {
+  background-color: #E0E0E0 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-400 {
+  background-color: #BDBDBD !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-500 {
+  background-color: #9E9E9E !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-600 {
+  background-color: #757575 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-700 {
+  background-color: #616161 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-800 {
+  background-color: #424242 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-grey .mdui-color-theme-900 {
+  background-color: #212121 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme {
+  background-color: #3F51B5 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-50 {
+  background-color: #E8EAF6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-100 {
+  background-color: #C5CAE9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-200 {
+  background-color: #9FA8DA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-300 {
+  background-color: #7986CB !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-400 {
+  background-color: #5C6BC0 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-500 {
+  background-color: #3F51B5 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-600 {
+  background-color: #3949AB !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-700 {
+  background-color: #303F9F !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-800 {
+  background-color: #283593 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-indigo .mdui-color-theme-900 {
+  background-color: #1A237E !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme {
+  background-color: #03A9F4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-50 {
+  background-color: #E1F5FE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-100 {
+  background-color: #B3E5FC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-200 {
+  background-color: #81D4FA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-300 {
+  background-color: #4FC3F7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-400 {
+  background-color: #29B6F6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-500 {
+  background-color: #03A9F4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-600 {
+  background-color: #039BE5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-700 {
+  background-color: #0288D1 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-800 {
+  background-color: #0277BD !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-light-blue .mdui-color-theme-900 {
+  background-color: #01579B !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme {
+  background-color: #8BC34A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-50 {
+  background-color: #F1F8E9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-100 {
+  background-color: #DCEDC8 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-200 {
+  background-color: #C5E1A5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-300 {
+  background-color: #AED581 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-400 {
+  background-color: #9CCC65 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-500 {
+  background-color: #8BC34A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-600 {
+  background-color: #7CB342 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-700 {
+  background-color: #689F38 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-800 {
+  background-color: #558B2F !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-light-green .mdui-color-theme-900 {
+  background-color: #33691E !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme {
+  background-color: #CDDC39 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-50 {
+  background-color: #F9FBE7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-100 {
+  background-color: #F0F4C3 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-200 {
+  background-color: #E6EE9C !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-300 {
+  background-color: #DCE775 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-400 {
+  background-color: #D4E157 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-500 {
+  background-color: #CDDC39 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-600 {
+  background-color: #C0CA33 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-700 {
+  background-color: #AFB42B !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-800 {
+  background-color: #9E9D24 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-lime .mdui-color-theme-900 {
+  background-color: #827717 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme {
+  background-color: #FF9800 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-50 {
+  background-color: #FFF3E0 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-100 {
+  background-color: #FFE0B2 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-200 {
+  background-color: #FFCC80 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-300 {
+  background-color: #FFB74D !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-400 {
+  background-color: #FFA726 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-500 {
+  background-color: #FF9800 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-600 {
+  background-color: #FB8C00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-700 {
+  background-color: #F57C00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-800 {
+  background-color: #EF6C00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-orange .mdui-color-theme-900 {
+  background-color: #E65100 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme {
+  background-color: #E91E63 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-50 {
+  background-color: #FCE4EC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-100 {
+  background-color: #F8BBD0 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-200 {
+  background-color: #F48FB1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-300 {
+  background-color: #F06292 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-400 {
+  background-color: #EC407A !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-500 {
+  background-color: #E91E63 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-600 {
+  background-color: #D81B60 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-700 {
+  background-color: #C2185B !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-800 {
+  background-color: #AD1457 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-pink .mdui-color-theme-900 {
+  background-color: #880E4F !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme {
+  background-color: #9C27B0 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-50 {
+  background-color: #F3E5F5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-100 {
+  background-color: #E1BEE7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-200 {
+  background-color: #CE93D8 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-300 {
+  background-color: #BA68C8 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-400 {
+  background-color: #AB47BC !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-500 {
+  background-color: #9C27B0 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-600 {
+  background-color: #8E24AA !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-700 {
+  background-color: #7B1FA2 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-800 {
+  background-color: #6A1B9A !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-purple .mdui-color-theme-900 {
+  background-color: #4A148C !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-red .mdui-color-theme {
+  background-color: #F44336 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-50 {
+  background-color: #FFEBEE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-100 {
+  background-color: #FFCDD2 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-200 {
+  background-color: #EF9A9A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-300 {
+  background-color: #E57373 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-400 {
+  background-color: #EF5350 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-500 {
+  background-color: #F44336 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-600 {
+  background-color: #E53935 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-700 {
+  background-color: #D32F2F !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-800 {
+  background-color: #C62828 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-red .mdui-color-theme-900 {
+  background-color: #B71C1C !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme {
+  background-color: #009688 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-50 {
+  background-color: #E0F2F1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-100 {
+  background-color: #B2DFDB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-200 {
+  background-color: #80CBC4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-300 {
+  background-color: #4DB6AC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-400 {
+  background-color: #26A69A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-500 {
+  background-color: #009688 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-600 {
+  background-color: #00897B !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-700 {
+  background-color: #00796B !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-800 {
+  background-color: #00695C !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-teal .mdui-color-theme-900 {
+  background-color: #004D40 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme {
+  background-color: #FFEB3B !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-50 {
+  background-color: #FFFDE7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-100 {
+  background-color: #FFF9C4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-200 {
+  background-color: #FFF59D !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-300 {
+  background-color: #FFF176 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-400 {
+  background-color: #FFEE58 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-500 {
+  background-color: #FFEB3B !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-600 {
+  background-color: #FDD835 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-700 {
+  background-color: #FBC02D !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-800 {
+  background-color: #F9A825 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-primary-yellow .mdui-color-theme-900 {
+  background-color: #F57F17 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+/**
+ * .mdui-theme-accent-[color] .mdui-color-theme-accent
+ * .mdui-theme-accent-[color] .mdui-color-theme-[degree]
+ */
+.mdui-theme-accent-amber .mdui-color-theme-accent {
+  background-color: #FFD740 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-amber .mdui-color-theme-a100 {
+  background-color: #FFE57F !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-amber .mdui-color-theme-a200 {
+  background-color: #FFD740 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-amber .mdui-color-theme-a400 {
+  background-color: #FFC400 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-amber .mdui-color-theme-a700 {
+  background-color: #FFAB00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-blue .mdui-color-theme-accent {
+  background-color: #448AFF !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-blue .mdui-color-theme-a100 {
+  background-color: #82B1FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-blue .mdui-color-theme-a200 {
+  background-color: #448AFF !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-blue .mdui-color-theme-a400 {
+  background-color: #2979FF !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-blue .mdui-color-theme-a700 {
+  background-color: #2962FF !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-cyan .mdui-color-theme-accent {
+  background-color: #18FFFF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-cyan .mdui-color-theme-a100 {
+  background-color: #84FFFF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-cyan .mdui-color-theme-a200 {
+  background-color: #18FFFF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-cyan .mdui-color-theme-a400 {
+  background-color: #00E5FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-cyan .mdui-color-theme-a700 {
+  background-color: #00B8D4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-deep-orange .mdui-color-theme-accent {
+  background-color: #FF6E40 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-deep-orange .mdui-color-theme-a100 {
+  background-color: #FF9E80 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-deep-orange .mdui-color-theme-a200 {
+  background-color: #FF6E40 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-deep-orange .mdui-color-theme-a400 {
+  background-color: #FF3D00 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-deep-orange .mdui-color-theme-a700 {
+  background-color: #DD2C00 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-deep-purple .mdui-color-theme-accent {
+  background-color: #7C4DFF !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-deep-purple .mdui-color-theme-a100 {
+  background-color: #B388FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-deep-purple .mdui-color-theme-a200 {
+  background-color: #7C4DFF !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-deep-purple .mdui-color-theme-a400 {
+  background-color: #651FFF !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-deep-purple .mdui-color-theme-a700 {
+  background-color: #6200EA !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-green .mdui-color-theme-accent {
+  background-color: #69F0AE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-green .mdui-color-theme-a100 {
+  background-color: #B9F6CA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-green .mdui-color-theme-a200 {
+  background-color: #69F0AE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-green .mdui-color-theme-a400 {
+  background-color: #00E676 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-green .mdui-color-theme-a700 {
+  background-color: #00C853 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-indigo .mdui-color-theme-accent {
+  background-color: #536DFE !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-indigo .mdui-color-theme-a100 {
+  background-color: #8C9EFF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-indigo .mdui-color-theme-a200 {
+  background-color: #536DFE !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-indigo .mdui-color-theme-a400 {
+  background-color: #3D5AFE !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-indigo .mdui-color-theme-a700 {
+  background-color: #304FFE !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-light-blue .mdui-color-theme-accent {
+  background-color: #40C4FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-light-blue .mdui-color-theme-a100 {
+  background-color: #80D8FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-light-blue .mdui-color-theme-a200 {
+  background-color: #40C4FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-light-blue .mdui-color-theme-a400 {
+  background-color: #00B0FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-light-blue .mdui-color-theme-a700 {
+  background-color: #0091EA !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-light-green .mdui-color-theme-accent {
+  background-color: #B2FF59 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-light-green .mdui-color-theme-a100 {
+  background-color: #CCFF90 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-light-green .mdui-color-theme-a200 {
+  background-color: #B2FF59 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-light-green .mdui-color-theme-a400 {
+  background-color: #76FF03 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-light-green .mdui-color-theme-a700 {
+  background-color: #64DD17 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-lime .mdui-color-theme-accent {
+  background-color: #EEFF41 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-lime .mdui-color-theme-a100 {
+  background-color: #F4FF81 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-lime .mdui-color-theme-a200 {
+  background-color: #EEFF41 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-lime .mdui-color-theme-a400 {
+  background-color: #C6FF00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-lime .mdui-color-theme-a700 {
+  background-color: #AEEA00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-orange .mdui-color-theme-accent {
+  background-color: #FFAB40 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-orange .mdui-color-theme-a100 {
+  background-color: #FFD180 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-orange .mdui-color-theme-a200 {
+  background-color: #FFAB40 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-orange .mdui-color-theme-a400 {
+  background-color: #FF9100 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-orange .mdui-color-theme-a700 {
+  background-color: #FF6D00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-pink .mdui-color-theme-accent {
+  background-color: #FF4081 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-pink .mdui-color-theme-a100 {
+  background-color: #FF80AB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-pink .mdui-color-theme-a200 {
+  background-color: #FF4081 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-pink .mdui-color-theme-a400 {
+  background-color: #F50057 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-pink .mdui-color-theme-a700 {
+  background-color: #C51162 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-purple .mdui-color-theme-accent {
+  background-color: #E040FB !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-purple .mdui-color-theme-a100 {
+  background-color: #EA80FC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-purple .mdui-color-theme-a200 {
+  background-color: #E040FB !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-purple .mdui-color-theme-a400 {
+  background-color: #D500F9 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-purple .mdui-color-theme-a700 {
+  background-color: #AA00FF !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-red .mdui-color-theme-accent {
+  background-color: #FF5252 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-red .mdui-color-theme-a100 {
+  background-color: #FF8A80 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-red .mdui-color-theme-a200 {
+  background-color: #FF5252 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-red .mdui-color-theme-a400 {
+  background-color: #FF1744 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-red .mdui-color-theme-a700 {
+  background-color: #D50000 !important;
+  color: #ffffff !important;
+}
+.mdui-theme-accent-teal .mdui-color-theme-accent {
+  background-color: #64FFDA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-teal .mdui-color-theme-a100 {
+  background-color: #A7FFEB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-teal .mdui-color-theme-a200 {
+  background-color: #64FFDA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-teal .mdui-color-theme-a400 {
+  background-color: #1DE9B6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-teal .mdui-color-theme-a700 {
+  background-color: #00BFA5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-yellow .mdui-color-theme-accent {
+  background-color: #FFFF00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-yellow .mdui-color-theme-a100 {
+  background-color: #FFFF8D !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-yellow .mdui-color-theme-a200 {
+  background-color: #FFFF00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-yellow .mdui-color-theme-a400 {
+  background-color: #FFEA00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-theme-accent-yellow .mdui-color-theme-a700 {
+  background-color: #FFD600 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+/**
+ * .mdui-color-[color]
+ * .mdui-color-[color]-[degree]
+ */
+.mdui-color-amber {
+  background-color: #FFC107 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-50 {
+  background-color: #FFF8E1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-100 {
+  background-color: #FFECB3 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-200 {
+  background-color: #FFE082 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-300 {
+  background-color: #FFD54F !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-400 {
+  background-color: #FFCA28 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-500 {
+  background-color: #FFC107 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-600 {
+  background-color: #FFB300 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-700 {
+  background-color: #FFA000 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-800 {
+  background-color: #FF8F00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-900 {
+  background-color: #FF6F00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue {
+  background-color: #2196F3 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-50 {
+  background-color: #E3F2FD !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-100 {
+  background-color: #BBDEFB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-200 {
+  background-color: #90CAF9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-300 {
+  background-color: #64B5F6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-400 {
+  background-color: #42A5F5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-500 {
+  background-color: #2196F3 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-600 {
+  background-color: #1E88E5 !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-700 {
+  background-color: #1976D2 !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-800 {
+  background-color: #1565C0 !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-900 {
+  background-color: #0D47A1 !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-grey {
+  background-color: #607D8B !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-grey-50 {
+  background-color: #ECEFF1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-grey-100 {
+  background-color: #CFD8DC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-grey-200 {
+  background-color: #B0BEC5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-grey-300 {
+  background-color: #90A4AE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-grey-400 {
+  background-color: #78909C !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-grey-500 {
+  background-color: #607D8B !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-grey-600 {
+  background-color: #546E7A !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-grey-700 {
+  background-color: #455A64 !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-grey-800 {
+  background-color: #37474F !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-grey-900 {
+  background-color: #263238 !important;
+  color: #ffffff !important;
+}
+.mdui-color-brown {
+  background-color: #795548 !important;
+  color: #ffffff !important;
+}
+.mdui-color-brown-50 {
+  background-color: #EFEBE9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-brown-100 {
+  background-color: #D7CCC8 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-brown-200 {
+  background-color: #BCAAA4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-brown-300 {
+  background-color: #A1887F !important;
+  color: #ffffff !important;
+}
+.mdui-color-brown-400 {
+  background-color: #8D6E63 !important;
+  color: #ffffff !important;
+}
+.mdui-color-brown-500 {
+  background-color: #795548 !important;
+  color: #ffffff !important;
+}
+.mdui-color-brown-600 {
+  background-color: #6D4C41 !important;
+  color: #ffffff !important;
+}
+.mdui-color-brown-700 {
+  background-color: #5D4037 !important;
+  color: #ffffff !important;
+}
+.mdui-color-brown-800 {
+  background-color: #4E342E !important;
+  color: #ffffff !important;
+}
+.mdui-color-brown-900 {
+  background-color: #3E2723 !important;
+  color: #ffffff !important;
+}
+.mdui-color-cyan {
+  background-color: #00BCD4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-50 {
+  background-color: #E0F7FA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-100 {
+  background-color: #B2EBF2 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-200 {
+  background-color: #80DEEA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-300 {
+  background-color: #4DD0E1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-400 {
+  background-color: #26C6DA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-500 {
+  background-color: #00BCD4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-600 {
+  background-color: #00ACC1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-700 {
+  background-color: #0097A7 !important;
+  color: #ffffff !important;
+}
+.mdui-color-cyan-800 {
+  background-color: #00838F !important;
+  color: #ffffff !important;
+}
+.mdui-color-cyan-900 {
+  background-color: #006064 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-orange {
+  background-color: #FF5722 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-50 {
+  background-color: #FBE9E7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-100 {
+  background-color: #FFCCBC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-200 {
+  background-color: #FFAB91 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-300 {
+  background-color: #FF8A65 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-400 {
+  background-color: #FF7043 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-500 {
+  background-color: #FF5722 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-600 {
+  background-color: #F4511E !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-orange-700 {
+  background-color: #E64A19 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-orange-800 {
+  background-color: #D84315 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-orange-900 {
+  background-color: #BF360C !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple {
+  background-color: #673AB7 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-50 {
+  background-color: #EDE7F6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-purple-100 {
+  background-color: #D1C4E9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-purple-200 {
+  background-color: #B39DDB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-purple-300 {
+  background-color: #9575CD !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-400 {
+  background-color: #7E57C2 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-500 {
+  background-color: #673AB7 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-600 {
+  background-color: #5E35B1 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-700 {
+  background-color: #512DA8 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-800 {
+  background-color: #4527A0 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-900 {
+  background-color: #311B92 !important;
+  color: #ffffff !important;
+}
+.mdui-color-green {
+  background-color: #4CAF50 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-50 {
+  background-color: #E8F5E9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-100 {
+  background-color: #C8E6C9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-200 {
+  background-color: #A5D6A7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-300 {
+  background-color: #81C784 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-400 {
+  background-color: #66BB6A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-500 {
+  background-color: #4CAF50 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-600 {
+  background-color: #43A047 !important;
+  color: #ffffff !important;
+}
+.mdui-color-green-700 {
+  background-color: #388E3C !important;
+  color: #ffffff !important;
+}
+.mdui-color-green-800 {
+  background-color: #2E7D32 !important;
+  color: #ffffff !important;
+}
+.mdui-color-green-900 {
+  background-color: #1B5E20 !important;
+  color: #ffffff !important;
+}
+.mdui-color-grey {
+  background-color: #9E9E9E !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-grey-50 {
+  background-color: #FAFAFA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-grey-100 {
+  background-color: #F5F5F5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-grey-200 {
+  background-color: #EEEEEE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-grey-300 {
+  background-color: #E0E0E0 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-grey-400 {
+  background-color: #BDBDBD !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-grey-500 {
+  background-color: #9E9E9E !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-grey-600 {
+  background-color: #757575 !important;
+  color: #ffffff !important;
+}
+.mdui-color-grey-700 {
+  background-color: #616161 !important;
+  color: #ffffff !important;
+}
+.mdui-color-grey-800 {
+  background-color: #424242 !important;
+  color: #ffffff !important;
+}
+.mdui-color-grey-900 {
+  background-color: #212121 !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo {
+  background-color: #3F51B5 !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-50 {
+  background-color: #E8EAF6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-indigo-100 {
+  background-color: #C5CAE9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-indigo-200 {
+  background-color: #9FA8DA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-indigo-300 {
+  background-color: #7986CB !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-400 {
+  background-color: #5C6BC0 !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-500 {
+  background-color: #3F51B5 !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-600 {
+  background-color: #3949AB !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-700 {
+  background-color: #303F9F !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-800 {
+  background-color: #283593 !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-900 {
+  background-color: #1A237E !important;
+  color: #ffffff !important;
+}
+.mdui-color-light-blue {
+  background-color: #03A9F4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-50 {
+  background-color: #E1F5FE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-100 {
+  background-color: #B3E5FC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-200 {
+  background-color: #81D4FA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-300 {
+  background-color: #4FC3F7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-400 {
+  background-color: #29B6F6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-500 {
+  background-color: #03A9F4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-600 {
+  background-color: #039BE5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-700 {
+  background-color: #0288D1 !important;
+  color: #ffffff !important;
+}
+.mdui-color-light-blue-800 {
+  background-color: #0277BD !important;
+  color: #ffffff !important;
+}
+.mdui-color-light-blue-900 {
+  background-color: #01579B !important;
+  color: #ffffff !important;
+}
+.mdui-color-light-green {
+  background-color: #8BC34A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-50 {
+  background-color: #F1F8E9 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-100 {
+  background-color: #DCEDC8 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-200 {
+  background-color: #C5E1A5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-300 {
+  background-color: #AED581 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-400 {
+  background-color: #9CCC65 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-500 {
+  background-color: #8BC34A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-600 {
+  background-color: #7CB342 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-700 {
+  background-color: #689F38 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-800 {
+  background-color: #558B2F !important;
+  color: #ffffff !important;
+}
+.mdui-color-light-green-900 {
+  background-color: #33691E !important;
+  color: #ffffff !important;
+}
+.mdui-color-lime {
+  background-color: #CDDC39 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-50 {
+  background-color: #F9FBE7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-100 {
+  background-color: #F0F4C3 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-200 {
+  background-color: #E6EE9C !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-300 {
+  background-color: #DCE775 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-400 {
+  background-color: #D4E157 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-500 {
+  background-color: #CDDC39 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-600 {
+  background-color: #C0CA33 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-700 {
+  background-color: #AFB42B !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-800 {
+  background-color: #9E9D24 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-900 {
+  background-color: #827717 !important;
+  color: #ffffff !important;
+}
+.mdui-color-orange {
+  background-color: #FF9800 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-50 {
+  background-color: #FFF3E0 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-100 {
+  background-color: #FFE0B2 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-200 {
+  background-color: #FFCC80 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-300 {
+  background-color: #FFB74D !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-400 {
+  background-color: #FFA726 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-500 {
+  background-color: #FF9800 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-600 {
+  background-color: #FB8C00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-700 {
+  background-color: #F57C00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-800 {
+  background-color: #EF6C00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-900 {
+  background-color: #E65100 !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink {
+  background-color: #E91E63 !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink-50 {
+  background-color: #FCE4EC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-pink-100 {
+  background-color: #F8BBD0 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-pink-200 {
+  background-color: #F48FB1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-pink-300 {
+  background-color: #F06292 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-pink-400 {
+  background-color: #EC407A !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink-500 {
+  background-color: #E91E63 !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink-600 {
+  background-color: #D81B60 !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink-700 {
+  background-color: #C2185B !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink-800 {
+  background-color: #AD1457 !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink-900 {
+  background-color: #880E4F !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple {
+  background-color: #9C27B0 !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-50 {
+  background-color: #F3E5F5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-purple-100 {
+  background-color: #E1BEE7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-purple-200 {
+  background-color: #CE93D8 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-purple-300 {
+  background-color: #BA68C8 !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-400 {
+  background-color: #AB47BC !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-500 {
+  background-color: #9C27B0 !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-600 {
+  background-color: #8E24AA !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-700 {
+  background-color: #7B1FA2 !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-800 {
+  background-color: #6A1B9A !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-900 {
+  background-color: #4A148C !important;
+  color: #ffffff !important;
+}
+.mdui-color-red {
+  background-color: #F44336 !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-50 {
+  background-color: #FFEBEE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-red-100 {
+  background-color: #FFCDD2 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-red-200 {
+  background-color: #EF9A9A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-red-300 {
+  background-color: #E57373 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-red-400 {
+  background-color: #EF5350 !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-500 {
+  background-color: #F44336 !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-600 {
+  background-color: #E53935 !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-700 {
+  background-color: #D32F2F !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-800 {
+  background-color: #C62828 !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-900 {
+  background-color: #B71C1C !important;
+  color: #ffffff !important;
+}
+.mdui-color-teal {
+  background-color: #009688 !important;
+  color: #ffffff !important;
+}
+.mdui-color-teal-50 {
+  background-color: #E0F2F1 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-teal-100 {
+  background-color: #B2DFDB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-teal-200 {
+  background-color: #80CBC4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-teal-300 {
+  background-color: #4DB6AC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-teal-400 {
+  background-color: #26A69A !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-teal-500 {
+  background-color: #009688 !important;
+  color: #ffffff !important;
+}
+.mdui-color-teal-600 {
+  background-color: #00897B !important;
+  color: #ffffff !important;
+}
+.mdui-color-teal-700 {
+  background-color: #00796B !important;
+  color: #ffffff !important;
+}
+.mdui-color-teal-800 {
+  background-color: #00695C !important;
+  color: #ffffff !important;
+}
+.mdui-color-teal-900 {
+  background-color: #004D40 !important;
+  color: #ffffff !important;
+}
+.mdui-color-yellow {
+  background-color: #FFEB3B !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-50 {
+  background-color: #FFFDE7 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-100 {
+  background-color: #FFF9C4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-200 {
+  background-color: #FFF59D !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-300 {
+  background-color: #FFF176 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-400 {
+  background-color: #FFEE58 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-500 {
+  background-color: #FFEB3B !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-600 {
+  background-color: #FDD835 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-700 {
+  background-color: #FBC02D !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-800 {
+  background-color: #F9A825 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-900 {
+  background-color: #F57F17 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+/**
+ * .mdui-color-[color]-accent
+ * .mdui-color-[color]-[degree]
+ */
+.mdui-color-amber-accent {
+  background-color: #FFD740 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-a100 {
+  background-color: #FFE57F !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-a200 {
+  background-color: #FFD740 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-a400 {
+  background-color: #FFC400 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-amber-a700 {
+  background-color: #FFAB00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-accent {
+  background-color: #448AFF !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-a100 {
+  background-color: #82B1FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-blue-a200 {
+  background-color: #448AFF !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-a400 {
+  background-color: #2979FF !important;
+  color: #ffffff !important;
+}
+.mdui-color-blue-a700 {
+  background-color: #2962FF !important;
+  color: #ffffff !important;
+}
+.mdui-color-cyan-accent {
+  background-color: #18FFFF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-a100 {
+  background-color: #84FFFF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-a200 {
+  background-color: #18FFFF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-a400 {
+  background-color: #00E5FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-cyan-a700 {
+  background-color: #00B8D4 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-accent {
+  background-color: #FF6E40 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-a100 {
+  background-color: #FF9E80 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-a200 {
+  background-color: #FF6E40 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-orange-a400 {
+  background-color: #FF3D00 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-orange-a700 {
+  background-color: #DD2C00 !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-accent {
+  background-color: #7C4DFF !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-a100 {
+  background-color: #B388FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-deep-purple-a200 {
+  background-color: #7C4DFF !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-a400 {
+  background-color: #651FFF !important;
+  color: #ffffff !important;
+}
+.mdui-color-deep-purple-a700 {
+  background-color: #6200EA !important;
+  color: #ffffff !important;
+}
+.mdui-color-green-accent {
+  background-color: #69F0AE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-a100 {
+  background-color: #B9F6CA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-a200 {
+  background-color: #69F0AE !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-a400 {
+  background-color: #00E676 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-green-a700 {
+  background-color: #00C853 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-indigo-accent {
+  background-color: #536DFE !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-a100 {
+  background-color: #8C9EFF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-indigo-a200 {
+  background-color: #536DFE !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-a400 {
+  background-color: #3D5AFE !important;
+  color: #ffffff !important;
+}
+.mdui-color-indigo-a700 {
+  background-color: #304FFE !important;
+  color: #ffffff !important;
+}
+.mdui-color-light-blue-accent {
+  background-color: #40C4FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-a100 {
+  background-color: #80D8FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-a200 {
+  background-color: #40C4FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-a400 {
+  background-color: #00B0FF !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-blue-a700 {
+  background-color: #0091EA !important;
+  color: #ffffff !important;
+}
+.mdui-color-light-green-accent {
+  background-color: #B2FF59 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-a100 {
+  background-color: #CCFF90 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-a200 {
+  background-color: #B2FF59 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-a400 {
+  background-color: #76FF03 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-light-green-a700 {
+  background-color: #64DD17 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-accent {
+  background-color: #EEFF41 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-a100 {
+  background-color: #F4FF81 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-a200 {
+  background-color: #EEFF41 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-a400 {
+  background-color: #C6FF00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-lime-a700 {
+  background-color: #AEEA00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-accent {
+  background-color: #FFAB40 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-a100 {
+  background-color: #FFD180 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-a200 {
+  background-color: #FFAB40 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-a400 {
+  background-color: #FF9100 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-orange-a700 {
+  background-color: #FF6D00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-pink-accent {
+  background-color: #FF4081 !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink-a100 {
+  background-color: #FF80AB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-pink-a200 {
+  background-color: #FF4081 !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink-a400 {
+  background-color: #F50057 !important;
+  color: #ffffff !important;
+}
+.mdui-color-pink-a700 {
+  background-color: #C51162 !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-accent {
+  background-color: #E040FB !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-a100 {
+  background-color: #EA80FC !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-purple-a200 {
+  background-color: #E040FB !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-a400 {
+  background-color: #D500F9 !important;
+  color: #ffffff !important;
+}
+.mdui-color-purple-a700 {
+  background-color: #AA00FF !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-accent {
+  background-color: #FF5252 !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-a100 {
+  background-color: #FF8A80 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-red-a200 {
+  background-color: #FF5252 !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-a400 {
+  background-color: #FF1744 !important;
+  color: #ffffff !important;
+}
+.mdui-color-red-a700 {
+  background-color: #D50000 !important;
+  color: #ffffff !important;
+}
+.mdui-color-teal-accent {
+  background-color: #64FFDA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-teal-a100 {
+  background-color: #A7FFEB !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-teal-a200 {
+  background-color: #64FFDA !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-teal-a400 {
+  background-color: #1DE9B6 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-teal-a700 {
+  background-color: #00BFA5 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-accent {
+  background-color: #FFFF00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-a100 {
+  background-color: #FFFF8D !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-a200 {
+  background-color: #FFFF00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-a400 {
+  background-color: #FFEA00 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-color-yellow-a700 {
+  background-color: #FFD600 !important;
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+/**
+ * .mdui-color-black
+ * .mdui-color-white
+ * .mdui-color-transparent
+ */
+.mdui-color-black {
+  color: #ffffff !important;
+  background-color: #000000 !important;
+}
+.mdui-color-white {
+  color: rgba(0, 0, 0, 0.87) !important;
+  background-color: #FFFFFF !important;
+}
+.mdui-color-transparent {
+  background-color: transparent !important;
+}
+/**
+ * .mdui-theme-primary-[color] .mdui-text-color-theme
+ * .mdui-theme-primary-[color] .mdui-text-color-theme-[degree]
+ */
+.mdui-theme-primary-amber .mdui-text-color-theme {
+  color: #FFC107 !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-50 {
+  color: #FFF8E1 !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-100 {
+  color: #FFECB3 !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-200 {
+  color: #FFE082 !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-300 {
+  color: #FFD54F !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-400 {
+  color: #FFCA28 !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-500 {
+  color: #FFC107 !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-600 {
+  color: #FFB300 !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-700 {
+  color: #FFA000 !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-800 {
+  color: #FF8F00 !important;
+}
+.mdui-theme-primary-amber .mdui-text-color-theme-900 {
+  color: #FF6F00 !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme {
+  color: #2196F3 !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-50 {
+  color: #E3F2FD !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-100 {
+  color: #BBDEFB !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-200 {
+  color: #90CAF9 !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-300 {
+  color: #64B5F6 !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-400 {
+  color: #42A5F5 !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-500 {
+  color: #2196F3 !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-600 {
+  color: #1E88E5 !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-700 {
+  color: #1976D2 !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-800 {
+  color: #1565C0 !important;
+}
+.mdui-theme-primary-blue .mdui-text-color-theme-900 {
+  color: #0D47A1 !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme {
+  color: #607D8B !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-50 {
+  color: #ECEFF1 !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-100 {
+  color: #CFD8DC !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-200 {
+  color: #B0BEC5 !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-300 {
+  color: #90A4AE !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-400 {
+  color: #78909C !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-500 {
+  color: #607D8B !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-600 {
+  color: #546E7A !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-700 {
+  color: #455A64 !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-800 {
+  color: #37474F !important;
+}
+.mdui-theme-primary-blue-grey .mdui-text-color-theme-900 {
+  color: #263238 !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme {
+  color: #795548 !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-50 {
+  color: #EFEBE9 !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-100 {
+  color: #D7CCC8 !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-200 {
+  color: #BCAAA4 !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-300 {
+  color: #A1887F !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-400 {
+  color: #8D6E63 !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-500 {
+  color: #795548 !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-600 {
+  color: #6D4C41 !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-700 {
+  color: #5D4037 !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-800 {
+  color: #4E342E !important;
+}
+.mdui-theme-primary-brown .mdui-text-color-theme-900 {
+  color: #3E2723 !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme {
+  color: #00BCD4 !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-50 {
+  color: #E0F7FA !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-100 {
+  color: #B2EBF2 !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-200 {
+  color: #80DEEA !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-300 {
+  color: #4DD0E1 !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-400 {
+  color: #26C6DA !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-500 {
+  color: #00BCD4 !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-600 {
+  color: #00ACC1 !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-700 {
+  color: #0097A7 !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-800 {
+  color: #00838F !important;
+}
+.mdui-theme-primary-cyan .mdui-text-color-theme-900 {
+  color: #006064 !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme {
+  color: #FF5722 !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-50 {
+  color: #FBE9E7 !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-100 {
+  color: #FFCCBC !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-200 {
+  color: #FFAB91 !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-300 {
+  color: #FF8A65 !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-400 {
+  color: #FF7043 !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-500 {
+  color: #FF5722 !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-600 {
+  color: #F4511E !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-700 {
+  color: #E64A19 !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-800 {
+  color: #D84315 !important;
+}
+.mdui-theme-primary-deep-orange .mdui-text-color-theme-900 {
+  color: #BF360C !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme {
+  color: #673AB7 !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-50 {
+  color: #EDE7F6 !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-100 {
+  color: #D1C4E9 !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-200 {
+  color: #B39DDB !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-300 {
+  color: #9575CD !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-400 {
+  color: #7E57C2 !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-500 {
+  color: #673AB7 !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-600 {
+  color: #5E35B1 !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-700 {
+  color: #512DA8 !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-800 {
+  color: #4527A0 !important;
+}
+.mdui-theme-primary-deep-purple .mdui-text-color-theme-900 {
+  color: #311B92 !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme {
+  color: #4CAF50 !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-50 {
+  color: #E8F5E9 !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-100 {
+  color: #C8E6C9 !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-200 {
+  color: #A5D6A7 !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-300 {
+  color: #81C784 !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-400 {
+  color: #66BB6A !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-500 {
+  color: #4CAF50 !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-600 {
+  color: #43A047 !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-700 {
+  color: #388E3C !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-800 {
+  color: #2E7D32 !important;
+}
+.mdui-theme-primary-green .mdui-text-color-theme-900 {
+  color: #1B5E20 !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme {
+  color: #9E9E9E !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-50 {
+  color: #FAFAFA !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-100 {
+  color: #F5F5F5 !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-200 {
+  color: #EEEEEE !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-300 {
+  color: #E0E0E0 !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-400 {
+  color: #BDBDBD !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-500 {
+  color: #9E9E9E !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-600 {
+  color: #757575 !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-700 {
+  color: #616161 !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-800 {
+  color: #424242 !important;
+}
+.mdui-theme-primary-grey .mdui-text-color-theme-900 {
+  color: #212121 !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme {
+  color: #3F51B5 !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-50 {
+  color: #E8EAF6 !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-100 {
+  color: #C5CAE9 !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-200 {
+  color: #9FA8DA !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-300 {
+  color: #7986CB !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-400 {
+  color: #5C6BC0 !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-500 {
+  color: #3F51B5 !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-600 {
+  color: #3949AB !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-700 {
+  color: #303F9F !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-800 {
+  color: #283593 !important;
+}
+.mdui-theme-primary-indigo .mdui-text-color-theme-900 {
+  color: #1A237E !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme {
+  color: #03A9F4 !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-50 {
+  color: #E1F5FE !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-100 {
+  color: #B3E5FC !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-200 {
+  color: #81D4FA !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-300 {
+  color: #4FC3F7 !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-400 {
+  color: #29B6F6 !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-500 {
+  color: #03A9F4 !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-600 {
+  color: #039BE5 !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-700 {
+  color: #0288D1 !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-800 {
+  color: #0277BD !important;
+}
+.mdui-theme-primary-light-blue .mdui-text-color-theme-900 {
+  color: #01579B !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme {
+  color: #8BC34A !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-50 {
+  color: #F1F8E9 !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-100 {
+  color: #DCEDC8 !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-200 {
+  color: #C5E1A5 !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-300 {
+  color: #AED581 !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-400 {
+  color: #9CCC65 !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-500 {
+  color: #8BC34A !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-600 {
+  color: #7CB342 !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-700 {
+  color: #689F38 !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-800 {
+  color: #558B2F !important;
+}
+.mdui-theme-primary-light-green .mdui-text-color-theme-900 {
+  color: #33691E !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme {
+  color: #CDDC39 !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-50 {
+  color: #F9FBE7 !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-100 {
+  color: #F0F4C3 !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-200 {
+  color: #E6EE9C !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-300 {
+  color: #DCE775 !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-400 {
+  color: #D4E157 !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-500 {
+  color: #CDDC39 !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-600 {
+  color: #C0CA33 !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-700 {
+  color: #AFB42B !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-800 {
+  color: #9E9D24 !important;
+}
+.mdui-theme-primary-lime .mdui-text-color-theme-900 {
+  color: #827717 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme {
+  color: #FF9800 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-50 {
+  color: #FFF3E0 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-100 {
+  color: #FFE0B2 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-200 {
+  color: #FFCC80 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-300 {
+  color: #FFB74D !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-400 {
+  color: #FFA726 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-500 {
+  color: #FF9800 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-600 {
+  color: #FB8C00 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-700 {
+  color: #F57C00 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-800 {
+  color: #EF6C00 !important;
+}
+.mdui-theme-primary-orange .mdui-text-color-theme-900 {
+  color: #E65100 !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme {
+  color: #E91E63 !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-50 {
+  color: #FCE4EC !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-100 {
+  color: #F8BBD0 !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-200 {
+  color: #F48FB1 !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-300 {
+  color: #F06292 !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-400 {
+  color: #EC407A !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-500 {
+  color: #E91E63 !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-600 {
+  color: #D81B60 !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-700 {
+  color: #C2185B !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-800 {
+  color: #AD1457 !important;
+}
+.mdui-theme-primary-pink .mdui-text-color-theme-900 {
+  color: #880E4F !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme {
+  color: #9C27B0 !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-50 {
+  color: #F3E5F5 !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-100 {
+  color: #E1BEE7 !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-200 {
+  color: #CE93D8 !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-300 {
+  color: #BA68C8 !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-400 {
+  color: #AB47BC !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-500 {
+  color: #9C27B0 !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-600 {
+  color: #8E24AA !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-700 {
+  color: #7B1FA2 !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-800 {
+  color: #6A1B9A !important;
+}
+.mdui-theme-primary-purple .mdui-text-color-theme-900 {
+  color: #4A148C !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme {
+  color: #F44336 !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-50 {
+  color: #FFEBEE !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-100 {
+  color: #FFCDD2 !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-200 {
+  color: #EF9A9A !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-300 {
+  color: #E57373 !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-400 {
+  color: #EF5350 !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-500 {
+  color: #F44336 !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-600 {
+  color: #E53935 !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-700 {
+  color: #D32F2F !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-800 {
+  color: #C62828 !important;
+}
+.mdui-theme-primary-red .mdui-text-color-theme-900 {
+  color: #B71C1C !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme {
+  color: #009688 !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-50 {
+  color: #E0F2F1 !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-100 {
+  color: #B2DFDB !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-200 {
+  color: #80CBC4 !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-300 {
+  color: #4DB6AC !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-400 {
+  color: #26A69A !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-500 {
+  color: #009688 !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-600 {
+  color: #00897B !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-700 {
+  color: #00796B !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-800 {
+  color: #00695C !important;
+}
+.mdui-theme-primary-teal .mdui-text-color-theme-900 {
+  color: #004D40 !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme {
+  color: #FFEB3B !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-50 {
+  color: #FFFDE7 !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-100 {
+  color: #FFF9C4 !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-200 {
+  color: #FFF59D !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-300 {
+  color: #FFF176 !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-400 {
+  color: #FFEE58 !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-500 {
+  color: #FFEB3B !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-600 {
+  color: #FDD835 !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-700 {
+  color: #FBC02D !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-800 {
+  color: #F9A825 !important;
+}
+.mdui-theme-primary-yellow .mdui-text-color-theme-900 {
+  color: #F57F17 !important;
+}
+/**
+ * .mdui-theme-accent-[color] .mdui-text-color-theme-accent
+ * .mdui-theme-accent-[color] .mdui-text-color-theme-[degree]
+ */
+.mdui-theme-accent-amber .mdui-text-color-theme-accent {
+  color: #FFD740 !important;
+}
+.mdui-theme-accent-amber .mdui-text-color-theme-a100 {
+  color: #FFE57F !important;
+}
+.mdui-theme-accent-amber .mdui-text-color-theme-a200 {
+  color: #FFD740 !important;
+}
+.mdui-theme-accent-amber .mdui-text-color-theme-a400 {
+  color: #FFC400 !important;
+}
+.mdui-theme-accent-amber .mdui-text-color-theme-a700 {
+  color: #FFAB00 !important;
+}
+.mdui-theme-accent-blue .mdui-text-color-theme-accent {
+  color: #448AFF !important;
+}
+.mdui-theme-accent-blue .mdui-text-color-theme-a100 {
+  color: #82B1FF !important;
+}
+.mdui-theme-accent-blue .mdui-text-color-theme-a200 {
+  color: #448AFF !important;
+}
+.mdui-theme-accent-blue .mdui-text-color-theme-a400 {
+  color: #2979FF !important;
+}
+.mdui-theme-accent-blue .mdui-text-color-theme-a700 {
+  color: #2962FF !important;
+}
+.mdui-theme-accent-cyan .mdui-text-color-theme-accent {
+  color: #18FFFF !important;
+}
+.mdui-theme-accent-cyan .mdui-text-color-theme-a100 {
+  color: #84FFFF !important;
+}
+.mdui-theme-accent-cyan .mdui-text-color-theme-a200 {
+  color: #18FFFF !important;
+}
+.mdui-theme-accent-cyan .mdui-text-color-theme-a400 {
+  color: #00E5FF !important;
+}
+.mdui-theme-accent-cyan .mdui-text-color-theme-a700 {
+  color: #00B8D4 !important;
+}
+.mdui-theme-accent-deep-orange .mdui-text-color-theme-accent {
+  color: #FF6E40 !important;
+}
+.mdui-theme-accent-deep-orange .mdui-text-color-theme-a100 {
+  color: #FF9E80 !important;
+}
+.mdui-theme-accent-deep-orange .mdui-text-color-theme-a200 {
+  color: #FF6E40 !important;
+}
+.mdui-theme-accent-deep-orange .mdui-text-color-theme-a400 {
+  color: #FF3D00 !important;
+}
+.mdui-theme-accent-deep-orange .mdui-text-color-theme-a700 {
+  color: #DD2C00 !important;
+}
+.mdui-theme-accent-deep-purple .mdui-text-color-theme-accent {
+  color: #7C4DFF !important;
+}
+.mdui-theme-accent-deep-purple .mdui-text-color-theme-a100 {
+  color: #B388FF !important;
+}
+.mdui-theme-accent-deep-purple .mdui-text-color-theme-a200 {
+  color: #7C4DFF !important;
+}
+.mdui-theme-accent-deep-purple .mdui-text-color-theme-a400 {
+  color: #651FFF !important;
+}
+.mdui-theme-accent-deep-purple .mdui-text-color-theme-a700 {
+  color: #6200EA !important;
+}
+.mdui-theme-accent-green .mdui-text-color-theme-accent {
+  color: #69F0AE !important;
+}
+.mdui-theme-accent-green .mdui-text-color-theme-a100 {
+  color: #B9F6CA !important;
+}
+.mdui-theme-accent-green .mdui-text-color-theme-a200 {
+  color: #69F0AE !important;
+}
+.mdui-theme-accent-green .mdui-text-color-theme-a400 {
+  color: #00E676 !important;
+}
+.mdui-theme-accent-green .mdui-text-color-theme-a700 {
+  color: #00C853 !important;
+}
+.mdui-theme-accent-indigo .mdui-text-color-theme-accent {
+  color: #536DFE !important;
+}
+.mdui-theme-accent-indigo .mdui-text-color-theme-a100 {
+  color: #8C9EFF !important;
+}
+.mdui-theme-accent-indigo .mdui-text-color-theme-a200 {
+  color: #536DFE !important;
+}
+.mdui-theme-accent-indigo .mdui-text-color-theme-a400 {
+  color: #3D5AFE !important;
+}
+.mdui-theme-accent-indigo .mdui-text-color-theme-a700 {
+  color: #304FFE !important;
+}
+.mdui-theme-accent-light-blue .mdui-text-color-theme-accent {
+  color: #40C4FF !important;
+}
+.mdui-theme-accent-light-blue .mdui-text-color-theme-a100 {
+  color: #80D8FF !important;
+}
+.mdui-theme-accent-light-blue .mdui-text-color-theme-a200 {
+  color: #40C4FF !important;
+}
+.mdui-theme-accent-light-blue .mdui-text-color-theme-a400 {
+  color: #00B0FF !important;
+}
+.mdui-theme-accent-light-blue .mdui-text-color-theme-a700 {
+  color: #0091EA !important;
+}
+.mdui-theme-accent-light-green .mdui-text-color-theme-accent {
+  color: #B2FF59 !important;
+}
+.mdui-theme-accent-light-green .mdui-text-color-theme-a100 {
+  color: #CCFF90 !important;
+}
+.mdui-theme-accent-light-green .mdui-text-color-theme-a200 {
+  color: #B2FF59 !important;
+}
+.mdui-theme-accent-light-green .mdui-text-color-theme-a400 {
+  color: #76FF03 !important;
+}
+.mdui-theme-accent-light-green .mdui-text-color-theme-a700 {
+  color: #64DD17 !important;
+}
+.mdui-theme-accent-lime .mdui-text-color-theme-accent {
+  color: #EEFF41 !important;
+}
+.mdui-theme-accent-lime .mdui-text-color-theme-a100 {
+  color: #F4FF81 !important;
+}
+.mdui-theme-accent-lime .mdui-text-color-theme-a200 {
+  color: #EEFF41 !important;
+}
+.mdui-theme-accent-lime .mdui-text-color-theme-a400 {
+  color: #C6FF00 !important;
+}
+.mdui-theme-accent-lime .mdui-text-color-theme-a700 {
+  color: #AEEA00 !important;
+}
+.mdui-theme-accent-orange .mdui-text-color-theme-accent {
+  color: #FFAB40 !important;
+}
+.mdui-theme-accent-orange .mdui-text-color-theme-a100 {
+  color: #FFD180 !important;
+}
+.mdui-theme-accent-orange .mdui-text-color-theme-a200 {
+  color: #FFAB40 !important;
+}
+.mdui-theme-accent-orange .mdui-text-color-theme-a400 {
+  color: #FF9100 !important;
+}
+.mdui-theme-accent-orange .mdui-text-color-theme-a700 {
+  color: #FF6D00 !important;
+}
+.mdui-theme-accent-pink .mdui-text-color-theme-accent {
+  color: #FF4081 !important;
+}
+.mdui-theme-accent-pink .mdui-text-color-theme-a100 {
+  color: #FF80AB !important;
+}
+.mdui-theme-accent-pink .mdui-text-color-theme-a200 {
+  color: #FF4081 !important;
+}
+.mdui-theme-accent-pink .mdui-text-color-theme-a400 {
+  color: #F50057 !important;
+}
+.mdui-theme-accent-pink .mdui-text-color-theme-a700 {
+  color: #C51162 !important;
+}
+.mdui-theme-accent-purple .mdui-text-color-theme-accent {
+  color: #E040FB !important;
+}
+.mdui-theme-accent-purple .mdui-text-color-theme-a100 {
+  color: #EA80FC !important;
+}
+.mdui-theme-accent-purple .mdui-text-color-theme-a200 {
+  color: #E040FB !important;
+}
+.mdui-theme-accent-purple .mdui-text-color-theme-a400 {
+  color: #D500F9 !important;
+}
+.mdui-theme-accent-purple .mdui-text-color-theme-a700 {
+  color: #AA00FF !important;
+}
+.mdui-theme-accent-red .mdui-text-color-theme-accent {
+  color: #FF5252 !important;
+}
+.mdui-theme-accent-red .mdui-text-color-theme-a100 {
+  color: #FF8A80 !important;
+}
+.mdui-theme-accent-red .mdui-text-color-theme-a200 {
+  color: #FF5252 !important;
+}
+.mdui-theme-accent-red .mdui-text-color-theme-a400 {
+  color: #FF1744 !important;
+}
+.mdui-theme-accent-red .mdui-text-color-theme-a700 {
+  color: #D50000 !important;
+}
+.mdui-theme-accent-teal .mdui-text-color-theme-accent {
+  color: #64FFDA !important;
+}
+.mdui-theme-accent-teal .mdui-text-color-theme-a100 {
+  color: #A7FFEB !important;
+}
+.mdui-theme-accent-teal .mdui-text-color-theme-a200 {
+  color: #64FFDA !important;
+}
+.mdui-theme-accent-teal .mdui-text-color-theme-a400 {
+  color: #1DE9B6 !important;
+}
+.mdui-theme-accent-teal .mdui-text-color-theme-a700 {
+  color: #00BFA5 !important;
+}
+.mdui-theme-accent-yellow .mdui-text-color-theme-accent {
+  color: #FFFF00 !important;
+}
+.mdui-theme-accent-yellow .mdui-text-color-theme-a100 {
+  color: #FFFF8D !important;
+}
+.mdui-theme-accent-yellow .mdui-text-color-theme-a200 {
+  color: #FFFF00 !important;
+}
+.mdui-theme-accent-yellow .mdui-text-color-theme-a400 {
+  color: #FFEA00 !important;
+}
+.mdui-theme-accent-yellow .mdui-text-color-theme-a700 {
+  color: #FFD600 !important;
+}
+/**
+ * .mdui-text-color-[color]
+ * .mdui-text-color-[color]-[degree]
+ */
+.mdui-text-color-amber {
+  color: #FFC107 !important;
+}
+.mdui-text-color-amber-50 {
+  color: #FFF8E1 !important;
+}
+.mdui-text-color-amber-100 {
+  color: #FFECB3 !important;
+}
+.mdui-text-color-amber-200 {
+  color: #FFE082 !important;
+}
+.mdui-text-color-amber-300 {
+  color: #FFD54F !important;
+}
+.mdui-text-color-amber-400 {
+  color: #FFCA28 !important;
+}
+.mdui-text-color-amber-500 {
+  color: #FFC107 !important;
+}
+.mdui-text-color-amber-600 {
+  color: #FFB300 !important;
+}
+.mdui-text-color-amber-700 {
+  color: #FFA000 !important;
+}
+.mdui-text-color-amber-800 {
+  color: #FF8F00 !important;
+}
+.mdui-text-color-amber-900 {
+  color: #FF6F00 !important;
+}
+.mdui-text-color-blue {
+  color: #2196F3 !important;
+}
+.mdui-text-color-blue-50 {
+  color: #E3F2FD !important;
+}
+.mdui-text-color-blue-100 {
+  color: #BBDEFB !important;
+}
+.mdui-text-color-blue-200 {
+  color: #90CAF9 !important;
+}
+.mdui-text-color-blue-300 {
+  color: #64B5F6 !important;
+}
+.mdui-text-color-blue-400 {
+  color: #42A5F5 !important;
+}
+.mdui-text-color-blue-500 {
+  color: #2196F3 !important;
+}
+.mdui-text-color-blue-600 {
+  color: #1E88E5 !important;
+}
+.mdui-text-color-blue-700 {
+  color: #1976D2 !important;
+}
+.mdui-text-color-blue-800 {
+  color: #1565C0 !important;
+}
+.mdui-text-color-blue-900 {
+  color: #0D47A1 !important;
+}
+.mdui-text-color-blue-grey {
+  color: #607D8B !important;
+}
+.mdui-text-color-blue-grey-50 {
+  color: #ECEFF1 !important;
+}
+.mdui-text-color-blue-grey-100 {
+  color: #CFD8DC !important;
+}
+.mdui-text-color-blue-grey-200 {
+  color: #B0BEC5 !important;
+}
+.mdui-text-color-blue-grey-300 {
+  color: #90A4AE !important;
+}
+.mdui-text-color-blue-grey-400 {
+  color: #78909C !important;
+}
+.mdui-text-color-blue-grey-500 {
+  color: #607D8B !important;
+}
+.mdui-text-color-blue-grey-600 {
+  color: #546E7A !important;
+}
+.mdui-text-color-blue-grey-700 {
+  color: #455A64 !important;
+}
+.mdui-text-color-blue-grey-800 {
+  color: #37474F !important;
+}
+.mdui-text-color-blue-grey-900 {
+  color: #263238 !important;
+}
+.mdui-text-color-brown {
+  color: #795548 !important;
+}
+.mdui-text-color-brown-50 {
+  color: #EFEBE9 !important;
+}
+.mdui-text-color-brown-100 {
+  color: #D7CCC8 !important;
+}
+.mdui-text-color-brown-200 {
+  color: #BCAAA4 !important;
+}
+.mdui-text-color-brown-300 {
+  color: #A1887F !important;
+}
+.mdui-text-color-brown-400 {
+  color: #8D6E63 !important;
+}
+.mdui-text-color-brown-500 {
+  color: #795548 !important;
+}
+.mdui-text-color-brown-600 {
+  color: #6D4C41 !important;
+}
+.mdui-text-color-brown-700 {
+  color: #5D4037 !important;
+}
+.mdui-text-color-brown-800 {
+  color: #4E342E !important;
+}
+.mdui-text-color-brown-900 {
+  color: #3E2723 !important;
+}
+.mdui-text-color-cyan {
+  color: #00BCD4 !important;
+}
+.mdui-text-color-cyan-50 {
+  color: #E0F7FA !important;
+}
+.mdui-text-color-cyan-100 {
+  color: #B2EBF2 !important;
+}
+.mdui-text-color-cyan-200 {
+  color: #80DEEA !important;
+}
+.mdui-text-color-cyan-300 {
+  color: #4DD0E1 !important;
+}
+.mdui-text-color-cyan-400 {
+  color: #26C6DA !important;
+}
+.mdui-text-color-cyan-500 {
+  color: #00BCD4 !important;
+}
+.mdui-text-color-cyan-600 {
+  color: #00ACC1 !important;
+}
+.mdui-text-color-cyan-700 {
+  color: #0097A7 !important;
+}
+.mdui-text-color-cyan-800 {
+  color: #00838F !important;
+}
+.mdui-text-color-cyan-900 {
+  color: #006064 !important;
+}
+.mdui-text-color-deep-orange {
+  color: #FF5722 !important;
+}
+.mdui-text-color-deep-orange-50 {
+  color: #FBE9E7 !important;
+}
+.mdui-text-color-deep-orange-100 {
+  color: #FFCCBC !important;
+}
+.mdui-text-color-deep-orange-200 {
+  color: #FFAB91 !important;
+}
+.mdui-text-color-deep-orange-300 {
+  color: #FF8A65 !important;
+}
+.mdui-text-color-deep-orange-400 {
+  color: #FF7043 !important;
+}
+.mdui-text-color-deep-orange-500 {
+  color: #FF5722 !important;
+}
+.mdui-text-color-deep-orange-600 {
+  color: #F4511E !important;
+}
+.mdui-text-color-deep-orange-700 {
+  color: #E64A19 !important;
+}
+.mdui-text-color-deep-orange-800 {
+  color: #D84315 !important;
+}
+.mdui-text-color-deep-orange-900 {
+  color: #BF360C !important;
+}
+.mdui-text-color-deep-purple {
+  color: #673AB7 !important;
+}
+.mdui-text-color-deep-purple-50 {
+  color: #EDE7F6 !important;
+}
+.mdui-text-color-deep-purple-100 {
+  color: #D1C4E9 !important;
+}
+.mdui-text-color-deep-purple-200 {
+  color: #B39DDB !important;
+}
+.mdui-text-color-deep-purple-300 {
+  color: #9575CD !important;
+}
+.mdui-text-color-deep-purple-400 {
+  color: #7E57C2 !important;
+}
+.mdui-text-color-deep-purple-500 {
+  color: #673AB7 !important;
+}
+.mdui-text-color-deep-purple-600 {
+  color: #5E35B1 !important;
+}
+.mdui-text-color-deep-purple-700 {
+  color: #512DA8 !important;
+}
+.mdui-text-color-deep-purple-800 {
+  color: #4527A0 !important;
+}
+.mdui-text-color-deep-purple-900 {
+  color: #311B92 !important;
+}
+.mdui-text-color-green {
+  color: #4CAF50 !important;
+}
+.mdui-text-color-green-50 {
+  color: #E8F5E9 !important;
+}
+.mdui-text-color-green-100 {
+  color: #C8E6C9 !important;
+}
+.mdui-text-color-green-200 {
+  color: #A5D6A7 !important;
+}
+.mdui-text-color-green-300 {
+  color: #81C784 !important;
+}
+.mdui-text-color-green-400 {
+  color: #66BB6A !important;
+}
+.mdui-text-color-green-500 {
+  color: #4CAF50 !important;
+}
+.mdui-text-color-green-600 {
+  color: #43A047 !important;
+}
+.mdui-text-color-green-700 {
+  color: #388E3C !important;
+}
+.mdui-text-color-green-800 {
+  color: #2E7D32 !important;
+}
+.mdui-text-color-green-900 {
+  color: #1B5E20 !important;
+}
+.mdui-text-color-grey {
+  color: #9E9E9E !important;
+}
+.mdui-text-color-grey-50 {
+  color: #FAFAFA !important;
+}
+.mdui-text-color-grey-100 {
+  color: #F5F5F5 !important;
+}
+.mdui-text-color-grey-200 {
+  color: #EEEEEE !important;
+}
+.mdui-text-color-grey-300 {
+  color: #E0E0E0 !important;
+}
+.mdui-text-color-grey-400 {
+  color: #BDBDBD !important;
+}
+.mdui-text-color-grey-500 {
+  color: #9E9E9E !important;
+}
+.mdui-text-color-grey-600 {
+  color: #757575 !important;
+}
+.mdui-text-color-grey-700 {
+  color: #616161 !important;
+}
+.mdui-text-color-grey-800 {
+  color: #424242 !important;
+}
+.mdui-text-color-grey-900 {
+  color: #212121 !important;
+}
+.mdui-text-color-indigo {
+  color: #3F51B5 !important;
+}
+.mdui-text-color-indigo-50 {
+  color: #E8EAF6 !important;
+}
+.mdui-text-color-indigo-100 {
+  color: #C5CAE9 !important;
+}
+.mdui-text-color-indigo-200 {
+  color: #9FA8DA !important;
+}
+.mdui-text-color-indigo-300 {
+  color: #7986CB !important;
+}
+.mdui-text-color-indigo-400 {
+  color: #5C6BC0 !important;
+}
+.mdui-text-color-indigo-500 {
+  color: #3F51B5 !important;
+}
+.mdui-text-color-indigo-600 {
+  color: #3949AB !important;
+}
+.mdui-text-color-indigo-700 {
+  color: #303F9F !important;
+}
+.mdui-text-color-indigo-800 {
+  color: #283593 !important;
+}
+.mdui-text-color-indigo-900 {
+  color: #1A237E !important;
+}
+.mdui-text-color-light-blue {
+  color: #03A9F4 !important;
+}
+.mdui-text-color-light-blue-50 {
+  color: #E1F5FE !important;
+}
+.mdui-text-color-light-blue-100 {
+  color: #B3E5FC !important;
+}
+.mdui-text-color-light-blue-200 {
+  color: #81D4FA !important;
+}
+.mdui-text-color-light-blue-300 {
+  color: #4FC3F7 !important;
+}
+.mdui-text-color-light-blue-400 {
+  color: #29B6F6 !important;
+}
+.mdui-text-color-light-blue-500 {
+  color: #03A9F4 !important;
+}
+.mdui-text-color-light-blue-600 {
+  color: #039BE5 !important;
+}
+.mdui-text-color-light-blue-700 {
+  color: #0288D1 !important;
+}
+.mdui-text-color-light-blue-800 {
+  color: #0277BD !important;
+}
+.mdui-text-color-light-blue-900 {
+  color: #01579B !important;
+}
+.mdui-text-color-light-green {
+  color: #8BC34A !important;
+}
+.mdui-text-color-light-green-50 {
+  color: #F1F8E9 !important;
+}
+.mdui-text-color-light-green-100 {
+  color: #DCEDC8 !important;
+}
+.mdui-text-color-light-green-200 {
+  color: #C5E1A5 !important;
+}
+.mdui-text-color-light-green-300 {
+  color: #AED581 !important;
+}
+.mdui-text-color-light-green-400 {
+  color: #9CCC65 !important;
+}
+.mdui-text-color-light-green-500 {
+  color: #8BC34A !important;
+}
+.mdui-text-color-light-green-600 {
+  color: #7CB342 !important;
+}
+.mdui-text-color-light-green-700 {
+  color: #689F38 !important;
+}
+.mdui-text-color-light-green-800 {
+  color: #558B2F !important;
+}
+.mdui-text-color-light-green-900 {
+  color: #33691E !important;
+}
+.mdui-text-color-lime {
+  color: #CDDC39 !important;
+}
+.mdui-text-color-lime-50 {
+  color: #F9FBE7 !important;
+}
+.mdui-text-color-lime-100 {
+  color: #F0F4C3 !important;
+}
+.mdui-text-color-lime-200 {
+  color: #E6EE9C !important;
+}
+.mdui-text-color-lime-300 {
+  color: #DCE775 !important;
+}
+.mdui-text-color-lime-400 {
+  color: #D4E157 !important;
+}
+.mdui-text-color-lime-500 {
+  color: #CDDC39 !important;
+}
+.mdui-text-color-lime-600 {
+  color: #C0CA33 !important;
+}
+.mdui-text-color-lime-700 {
+  color: #AFB42B !important;
+}
+.mdui-text-color-lime-800 {
+  color: #9E9D24 !important;
+}
+.mdui-text-color-lime-900 {
+  color: #827717 !important;
+}
+.mdui-text-color-orange {
+  color: #FF9800 !important;
+}
+.mdui-text-color-orange-50 {
+  color: #FFF3E0 !important;
+}
+.mdui-text-color-orange-100 {
+  color: #FFE0B2 !important;
+}
+.mdui-text-color-orange-200 {
+  color: #FFCC80 !important;
+}
+.mdui-text-color-orange-300 {
+  color: #FFB74D !important;
+}
+.mdui-text-color-orange-400 {
+  color: #FFA726 !important;
+}
+.mdui-text-color-orange-500 {
+  color: #FF9800 !important;
+}
+.mdui-text-color-orange-600 {
+  color: #FB8C00 !important;
+}
+.mdui-text-color-orange-700 {
+  color: #F57C00 !important;
+}
+.mdui-text-color-orange-800 {
+  color: #EF6C00 !important;
+}
+.mdui-text-color-orange-900 {
+  color: #E65100 !important;
+}
+.mdui-text-color-pink {
+  color: #E91E63 !important;
+}
+.mdui-text-color-pink-50 {
+  color: #FCE4EC !important;
+}
+.mdui-text-color-pink-100 {
+  color: #F8BBD0 !important;
+}
+.mdui-text-color-pink-200 {
+  color: #F48FB1 !important;
+}
+.mdui-text-color-pink-300 {
+  color: #F06292 !important;
+}
+.mdui-text-color-pink-400 {
+  color: #EC407A !important;
+}
+.mdui-text-color-pink-500 {
+  color: #E91E63 !important;
+}
+.mdui-text-color-pink-600 {
+  color: #D81B60 !important;
+}
+.mdui-text-color-pink-700 {
+  color: #C2185B !important;
+}
+.mdui-text-color-pink-800 {
+  color: #AD1457 !important;
+}
+.mdui-text-color-pink-900 {
+  color: #880E4F !important;
+}
+.mdui-text-color-purple {
+  color: #9C27B0 !important;
+}
+.mdui-text-color-purple-50 {
+  color: #F3E5F5 !important;
+}
+.mdui-text-color-purple-100 {
+  color: #E1BEE7 !important;
+}
+.mdui-text-color-purple-200 {
+  color: #CE93D8 !important;
+}
+.mdui-text-color-purple-300 {
+  color: #BA68C8 !important;
+}
+.mdui-text-color-purple-400 {
+  color: #AB47BC !important;
+}
+.mdui-text-color-purple-500 {
+  color: #9C27B0 !important;
+}
+.mdui-text-color-purple-600 {
+  color: #8E24AA !important;
+}
+.mdui-text-color-purple-700 {
+  color: #7B1FA2 !important;
+}
+.mdui-text-color-purple-800 {
+  color: #6A1B9A !important;
+}
+.mdui-text-color-purple-900 {
+  color: #4A148C !important;
+}
+.mdui-text-color-red {
+  color: #F44336 !important;
+}
+.mdui-text-color-red-50 {
+  color: #FFEBEE !important;
+}
+.mdui-text-color-red-100 {
+  color: #FFCDD2 !important;
+}
+.mdui-text-color-red-200 {
+  color: #EF9A9A !important;
+}
+.mdui-text-color-red-300 {
+  color: #E57373 !important;
+}
+.mdui-text-color-red-400 {
+  color: #EF5350 !important;
+}
+.mdui-text-color-red-500 {
+  color: #F44336 !important;
+}
+.mdui-text-color-red-600 {
+  color: #E53935 !important;
+}
+.mdui-text-color-red-700 {
+  color: #D32F2F !important;
+}
+.mdui-text-color-red-800 {
+  color: #C62828 !important;
+}
+.mdui-text-color-red-900 {
+  color: #B71C1C !important;
+}
+.mdui-text-color-teal {
+  color: #009688 !important;
+}
+.mdui-text-color-teal-50 {
+  color: #E0F2F1 !important;
+}
+.mdui-text-color-teal-100 {
+  color: #B2DFDB !important;
+}
+.mdui-text-color-teal-200 {
+  color: #80CBC4 !important;
+}
+.mdui-text-color-teal-300 {
+  color: #4DB6AC !important;
+}
+.mdui-text-color-teal-400 {
+  color: #26A69A !important;
+}
+.mdui-text-color-teal-500 {
+  color: #009688 !important;
+}
+.mdui-text-color-teal-600 {
+  color: #00897B !important;
+}
+.mdui-text-color-teal-700 {
+  color: #00796B !important;
+}
+.mdui-text-color-teal-800 {
+  color: #00695C !important;
+}
+.mdui-text-color-teal-900 {
+  color: #004D40 !important;
+}
+.mdui-text-color-yellow {
+  color: #FFEB3B !important;
+}
+.mdui-text-color-yellow-50 {
+  color: #FFFDE7 !important;
+}
+.mdui-text-color-yellow-100 {
+  color: #FFF9C4 !important;
+}
+.mdui-text-color-yellow-200 {
+  color: #FFF59D !important;
+}
+.mdui-text-color-yellow-300 {
+  color: #FFF176 !important;
+}
+.mdui-text-color-yellow-400 {
+  color: #FFEE58 !important;
+}
+.mdui-text-color-yellow-500 {
+  color: #FFEB3B !important;
+}
+.mdui-text-color-yellow-600 {
+  color: #FDD835 !important;
+}
+.mdui-text-color-yellow-700 {
+  color: #FBC02D !important;
+}
+.mdui-text-color-yellow-800 {
+  color: #F9A825 !important;
+}
+.mdui-text-color-yellow-900 {
+  color: #F57F17 !important;
+}
+/**
+ * .mdui-text-color-[color]-accent
+ * .mdui-text-color-[color]-[degree]
+ */
+.mdui-text-color-amber-accent {
+  color: #FFD740 !important;
+}
+.mdui-text-color-amber-a100 {
+  color: #FFE57F !important;
+}
+.mdui-text-color-amber-a200 {
+  color: #FFD740 !important;
+}
+.mdui-text-color-amber-a400 {
+  color: #FFC400 !important;
+}
+.mdui-text-color-amber-a700 {
+  color: #FFAB00 !important;
+}
+.mdui-text-color-blue-accent {
+  color: #448AFF !important;
+}
+.mdui-text-color-blue-a100 {
+  color: #82B1FF !important;
+}
+.mdui-text-color-blue-a200 {
+  color: #448AFF !important;
+}
+.mdui-text-color-blue-a400 {
+  color: #2979FF !important;
+}
+.mdui-text-color-blue-a700 {
+  color: #2962FF !important;
+}
+.mdui-text-color-cyan-accent {
+  color: #18FFFF !important;
+}
+.mdui-text-color-cyan-a100 {
+  color: #84FFFF !important;
+}
+.mdui-text-color-cyan-a200 {
+  color: #18FFFF !important;
+}
+.mdui-text-color-cyan-a400 {
+  color: #00E5FF !important;
+}
+.mdui-text-color-cyan-a700 {
+  color: #00B8D4 !important;
+}
+.mdui-text-color-deep-orange-accent {
+  color: #FF6E40 !important;
+}
+.mdui-text-color-deep-orange-a100 {
+  color: #FF9E80 !important;
+}
+.mdui-text-color-deep-orange-a200 {
+  color: #FF6E40 !important;
+}
+.mdui-text-color-deep-orange-a400 {
+  color: #FF3D00 !important;
+}
+.mdui-text-color-deep-orange-a700 {
+  color: #DD2C00 !important;
+}
+.mdui-text-color-deep-purple-accent {
+  color: #7C4DFF !important;
+}
+.mdui-text-color-deep-purple-a100 {
+  color: #B388FF !important;
+}
+.mdui-text-color-deep-purple-a200 {
+  color: #7C4DFF !important;
+}
+.mdui-text-color-deep-purple-a400 {
+  color: #651FFF !important;
+}
+.mdui-text-color-deep-purple-a700 {
+  color: #6200EA !important;
+}
+.mdui-text-color-green-accent {
+  color: #69F0AE !important;
+}
+.mdui-text-color-green-a100 {
+  color: #B9F6CA !important;
+}
+.mdui-text-color-green-a200 {
+  color: #69F0AE !important;
+}
+.mdui-text-color-green-a400 {
+  color: #00E676 !important;
+}
+.mdui-text-color-green-a700 {
+  color: #00C853 !important;
+}
+.mdui-text-color-indigo-accent {
+  color: #536DFE !important;
+}
+.mdui-text-color-indigo-a100 {
+  color: #8C9EFF !important;
+}
+.mdui-text-color-indigo-a200 {
+  color: #536DFE !important;
+}
+.mdui-text-color-indigo-a400 {
+  color: #3D5AFE !important;
+}
+.mdui-text-color-indigo-a700 {
+  color: #304FFE !important;
+}
+.mdui-text-color-light-blue-accent {
+  color: #40C4FF !important;
+}
+.mdui-text-color-light-blue-a100 {
+  color: #80D8FF !important;
+}
+.mdui-text-color-light-blue-a200 {
+  color: #40C4FF !important;
+}
+.mdui-text-color-light-blue-a400 {
+  color: #00B0FF !important;
+}
+.mdui-text-color-light-blue-a700 {
+  color: #0091EA !important;
+}
+.mdui-text-color-light-green-accent {
+  color: #B2FF59 !important;
+}
+.mdui-text-color-light-green-a100 {
+  color: #CCFF90 !important;
+}
+.mdui-text-color-light-green-a200 {
+  color: #B2FF59 !important;
+}
+.mdui-text-color-light-green-a400 {
+  color: #76FF03 !important;
+}
+.mdui-text-color-light-green-a700 {
+  color: #64DD17 !important;
+}
+.mdui-text-color-lime-accent {
+  color: #EEFF41 !important;
+}
+.mdui-text-color-lime-a100 {
+  color: #F4FF81 !important;
+}
+.mdui-text-color-lime-a200 {
+  color: #EEFF41 !important;
+}
+.mdui-text-color-lime-a400 {
+  color: #C6FF00 !important;
+}
+.mdui-text-color-lime-a700 {
+  color: #AEEA00 !important;
+}
+.mdui-text-color-orange-accent {
+  color: #FFAB40 !important;
+}
+.mdui-text-color-orange-a100 {
+  color: #FFD180 !important;
+}
+.mdui-text-color-orange-a200 {
+  color: #FFAB40 !important;
+}
+.mdui-text-color-orange-a400 {
+  color: #FF9100 !important;
+}
+.mdui-text-color-orange-a700 {
+  color: #FF6D00 !important;
+}
+.mdui-text-color-pink-accent {
+  color: #FF4081 !important;
+}
+.mdui-text-color-pink-a100 {
+  color: #FF80AB !important;
+}
+.mdui-text-color-pink-a200 {
+  color: #FF4081 !important;
+}
+.mdui-text-color-pink-a400 {
+  color: #F50057 !important;
+}
+.mdui-text-color-pink-a700 {
+  color: #C51162 !important;
+}
+.mdui-text-color-purple-accent {
+  color: #E040FB !important;
+}
+.mdui-text-color-purple-a100 {
+  color: #EA80FC !important;
+}
+.mdui-text-color-purple-a200 {
+  color: #E040FB !important;
+}
+.mdui-text-color-purple-a400 {
+  color: #D500F9 !important;
+}
+.mdui-text-color-purple-a700 {
+  color: #AA00FF !important;
+}
+.mdui-text-color-red-accent {
+  color: #FF5252 !important;
+}
+.mdui-text-color-red-a100 {
+  color: #FF8A80 !important;
+}
+.mdui-text-color-red-a200 {
+  color: #FF5252 !important;
+}
+.mdui-text-color-red-a400 {
+  color: #FF1744 !important;
+}
+.mdui-text-color-red-a700 {
+  color: #D50000 !important;
+}
+.mdui-text-color-teal-accent {
+  color: #64FFDA !important;
+}
+.mdui-text-color-teal-a100 {
+  color: #A7FFEB !important;
+}
+.mdui-text-color-teal-a200 {
+  color: #64FFDA !important;
+}
+.mdui-text-color-teal-a400 {
+  color: #1DE9B6 !important;
+}
+.mdui-text-color-teal-a700 {
+  color: #00BFA5 !important;
+}
+.mdui-text-color-yellow-accent {
+  color: #FFFF00 !important;
+}
+.mdui-text-color-yellow-a100 {
+  color: #FFFF8D !important;
+}
+.mdui-text-color-yellow-a200 {
+  color: #FFFF00 !important;
+}
+.mdui-text-color-yellow-a400 {
+  color: #FFEA00 !important;
+}
+.mdui-text-color-yellow-a700 {
+  color: #FFD600 !important;
+}
+/**
+ * .mdui-text-color-black
+ * .mdui-text-color-black-[]
+ * .mdui-text-color-theme-[]
+ */
+.mdui-text-color-black {
+  color: #000000 !important;
+}
+.mdui-text-color-black-text,
+.mdui-text-color-theme-text {
+  color: rgba(0, 0, 0, 0.87) !important;
+}
+.mdui-text-color-black-secondary,
+.mdui-text-color-theme-secondary {
+  color: rgba(0, 0, 0, 0.54) !important;
+}
+.mdui-text-color-black-disabled,
+.mdui-text-color-theme-disabled {
+  color: rgba(0, 0, 0, 0.38) !important;
+}
+.mdui-text-color-black-divider,
+.mdui-text-color-theme-divider {
+  color: rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-text-color-black-icon,
+.mdui-text-color-theme-icon {
+  color: rgba(0, 0, 0, 0.54) !important;
+}
+.mdui-text-color-black-icon-disabled,
+.mdui-text-color-theme-icon-disabled {
+  color: rgba(0, 0, 0, 0.26) !important;
+}
+/**
+ * .mdui-text-color-white
+ * .mdui-text-color-white-[]
+ */
+.mdui-text-color-white {
+  color: #FFFFFF !important;
+}
+.mdui-text-color-white-text {
+  color: #ffffff !important;
+}
+.mdui-text-color-white-secondary {
+  color: rgba(255, 255, 255, 0.7) !important;
+}
+.mdui-text-color-white-disabled {
+  color: rgba(255, 255, 255, 0.5) !important;
+}
+.mdui-text-color-white-divider {
+  color: rgba(255, 255, 255, 0.12) !important;
+}
+.mdui-text-color-white-icon {
+  color: #ffffff !important;
+}
+.mdui-text-color-white-icon-disabled {
+  color: rgba(255, 255, 255, 0.3) !important;
+}
+/**
+ * .mdui-text-color-theme-[] 深色主题
+ */
+.mdui-theme-layout-dark .mdui-text-color-theme-text {
+  color: #ffffff !important;
+}
+.mdui-theme-layout-dark .mdui-text-color-theme-secondary {
+  color: rgba(255, 255, 255, 0.7) !important;
+}
+.mdui-theme-layout-dark .mdui-text-color-theme-disabled {
+  color: rgba(255, 255, 255, 0.5) !important;
+}
+.mdui-theme-layout-dark .mdui-text-color-theme-divider {
+  color: rgba(255, 255, 255, 0.12) !important;
+}
+.mdui-theme-layout-dark .mdui-text-color-theme-icon {
+  color: #ffffff !important;
+}
+.mdui-theme-layout-dark .mdui-text-color-theme-icon-disabled {
+  color: rgba(255, 255, 255, 0.3) !important;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-text-color-theme-text {
+    color: #ffffff !important;
+  }
+  .mdui-theme-layout-auto .mdui-text-color-theme-secondary {
+    color: rgba(255, 255, 255, 0.7) !important;
+  }
+  .mdui-theme-layout-auto .mdui-text-color-theme-disabled {
+    color: rgba(255, 255, 255, 0.5) !important;
+  }
+  .mdui-theme-layout-auto .mdui-text-color-theme-divider {
+    color: rgba(255, 255, 255, 0.12) !important;
+  }
+  .mdui-theme-layout-auto .mdui-text-color-theme-icon {
+    color: #ffffff !important;
+  }
+  .mdui-theme-layout-auto .mdui-text-color-theme-icon-disabled {
+    color: rgba(255, 255, 255, 0.3) !important;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Helper 辅助类   ************
+ * =============================================================================
+ */
+/**
+ * =================== 边距
+ */
+.mdui-m-a-0 {
+  margin: 0px !important;
+}
+.mdui-m-t-0 {
+  margin-top: 0px !important;
+}
+.mdui-m-r-0 {
+  margin-right: 0px !important;
+}
+.mdui-m-b-0 {
+  margin-bottom: 0px !important;
+}
+.mdui-m-l-0 {
+  margin-left: 0px !important;
+}
+.mdui-m-x-0 {
+  margin-right: 0px !important;
+  margin-left: 0px !important;
+}
+.mdui-m-y-0 {
+  margin-top: 0px !important;
+  margin-bottom: 0px !important;
+}
+.mdui-p-a-0 {
+  padding: 0px !important;
+}
+.mdui-p-t-0 {
+  padding-top: 0px !important;
+}
+.mdui-p-r-0 {
+  padding-right: 0px !important;
+}
+.mdui-p-b-0 {
+  padding-bottom: 0px !important;
+}
+.mdui-p-l-0 {
+  padding-left: 0px !important;
+}
+.mdui-p-x-0 {
+  padding-right: 0px !important;
+  padding-left: 0px !important;
+}
+.mdui-p-y-0 {
+  padding-top: 0px !important;
+  padding-bottom: 0px !important;
+}
+.mdui-m-a-1 {
+  margin: 8px !important;
+}
+.mdui-m-t-1 {
+  margin-top: 8px !important;
+}
+.mdui-m-r-1 {
+  margin-right: 8px !important;
+}
+.mdui-m-b-1 {
+  margin-bottom: 8px !important;
+}
+.mdui-m-l-1 {
+  margin-left: 8px !important;
+}
+.mdui-m-x-1 {
+  margin-right: 8px !important;
+  margin-left: 8px !important;
+}
+.mdui-m-y-1 {
+  margin-top: 8px !important;
+  margin-bottom: 8px !important;
+}
+.mdui-p-a-1 {
+  padding: 8px !important;
+}
+.mdui-p-t-1 {
+  padding-top: 8px !important;
+}
+.mdui-p-r-1 {
+  padding-right: 8px !important;
+}
+.mdui-p-b-1 {
+  padding-bottom: 8px !important;
+}
+.mdui-p-l-1 {
+  padding-left: 8px !important;
+}
+.mdui-p-x-1 {
+  padding-right: 8px !important;
+  padding-left: 8px !important;
+}
+.mdui-p-y-1 {
+  padding-top: 8px !important;
+  padding-bottom: 8px !important;
+}
+.mdui-m-a-2 {
+  margin: 16px !important;
+}
+.mdui-m-t-2 {
+  margin-top: 16px !important;
+}
+.mdui-m-r-2 {
+  margin-right: 16px !important;
+}
+.mdui-m-b-2 {
+  margin-bottom: 16px !important;
+}
+.mdui-m-l-2 {
+  margin-left: 16px !important;
+}
+.mdui-m-x-2 {
+  margin-right: 16px !important;
+  margin-left: 16px !important;
+}
+.mdui-m-y-2 {
+  margin-top: 16px !important;
+  margin-bottom: 16px !important;
+}
+.mdui-p-a-2 {
+  padding: 16px !important;
+}
+.mdui-p-t-2 {
+  padding-top: 16px !important;
+}
+.mdui-p-r-2 {
+  padding-right: 16px !important;
+}
+.mdui-p-b-2 {
+  padding-bottom: 16px !important;
+}
+.mdui-p-l-2 {
+  padding-left: 16px !important;
+}
+.mdui-p-x-2 {
+  padding-right: 16px !important;
+  padding-left: 16px !important;
+}
+.mdui-p-y-2 {
+  padding-top: 16px !important;
+  padding-bottom: 16px !important;
+}
+.mdui-m-a-3 {
+  margin: 24px !important;
+}
+.mdui-m-t-3 {
+  margin-top: 24px !important;
+}
+.mdui-m-r-3 {
+  margin-right: 24px !important;
+}
+.mdui-m-b-3 {
+  margin-bottom: 24px !important;
+}
+.mdui-m-l-3 {
+  margin-left: 24px !important;
+}
+.mdui-m-x-3 {
+  margin-right: 24px !important;
+  margin-left: 24px !important;
+}
+.mdui-m-y-3 {
+  margin-top: 24px !important;
+  margin-bottom: 24px !important;
+}
+.mdui-p-a-3 {
+  padding: 24px !important;
+}
+.mdui-p-t-3 {
+  padding-top: 24px !important;
+}
+.mdui-p-r-3 {
+  padding-right: 24px !important;
+}
+.mdui-p-b-3 {
+  padding-bottom: 24px !important;
+}
+.mdui-p-l-3 {
+  padding-left: 24px !important;
+}
+.mdui-p-x-3 {
+  padding-right: 24px !important;
+  padding-left: 24px !important;
+}
+.mdui-p-y-3 {
+  padding-top: 24px !important;
+  padding-bottom: 24px !important;
+}
+.mdui-m-a-4 {
+  margin: 32px !important;
+}
+.mdui-m-t-4 {
+  margin-top: 32px !important;
+}
+.mdui-m-r-4 {
+  margin-right: 32px !important;
+}
+.mdui-m-b-4 {
+  margin-bottom: 32px !important;
+}
+.mdui-m-l-4 {
+  margin-left: 32px !important;
+}
+.mdui-m-x-4 {
+  margin-right: 32px !important;
+  margin-left: 32px !important;
+}
+.mdui-m-y-4 {
+  margin-top: 32px !important;
+  margin-bottom: 32px !important;
+}
+.mdui-p-a-4 {
+  padding: 32px !important;
+}
+.mdui-p-t-4 {
+  padding-top: 32px !important;
+}
+.mdui-p-r-4 {
+  padding-right: 32px !important;
+}
+.mdui-p-b-4 {
+  padding-bottom: 32px !important;
+}
+.mdui-p-l-4 {
+  padding-left: 32px !important;
+}
+.mdui-p-x-4 {
+  padding-right: 32px !important;
+  padding-left: 32px !important;
+}
+.mdui-p-y-4 {
+  padding-top: 32px !important;
+  padding-bottom: 32px !important;
+}
+.mdui-m-a-5 {
+  margin: 40px !important;
+}
+.mdui-m-t-5 {
+  margin-top: 40px !important;
+}
+.mdui-m-r-5 {
+  margin-right: 40px !important;
+}
+.mdui-m-b-5 {
+  margin-bottom: 40px !important;
+}
+.mdui-m-l-5 {
+  margin-left: 40px !important;
+}
+.mdui-m-x-5 {
+  margin-right: 40px !important;
+  margin-left: 40px !important;
+}
+.mdui-m-y-5 {
+  margin-top: 40px !important;
+  margin-bottom: 40px !important;
+}
+.mdui-p-a-5 {
+  padding: 40px !important;
+}
+.mdui-p-t-5 {
+  padding-top: 40px !important;
+}
+.mdui-p-r-5 {
+  padding-right: 40px !important;
+}
+.mdui-p-b-5 {
+  padding-bottom: 40px !important;
+}
+.mdui-p-l-5 {
+  padding-left: 40px !important;
+}
+.mdui-p-x-5 {
+  padding-right: 40px !important;
+  padding-left: 40px !important;
+}
+.mdui-p-y-5 {
+  padding-top: 40px !important;
+  padding-bottom: 40px !important;
+}
+/**
+ * ======================== 快速浮动
+ */
+/* 向左浮动 */
+.mdui-float-left {
+  float: left !important;
+}
+/* 向右浮动 */
+.mdui-float-right {
+  float: right !important;
+}
+/**
+ * ========================= 水平居中
+ */
+/* 水平居中 */
+.mdui-center {
+  display: block !important;
+  margin-right: auto !important;
+  margin-left: auto !important;
+}
+/**
+ * ========================= 垂直居中
+ */
+/* 垂直居中 */
+.mdui-valign {
+  display: -webkit-box !important;
+  display: -ms-flexbox !important;
+  display: flex !important;
+  -webkit-box-align: center !important;
+      -ms-flex-align: center !important;
+          align-items: center !important;
+}
+/**
+ * ========================= 文本对齐方式
+ */
+/* 文本左对齐 */
+.mdui-text-left {
+  text-align: left !important;
+}
+/* 文本居中对齐 */
+.mdui-text-center {
+  text-align: center !important;
+}
+/* 文本向右对齐 */
+.mdui-text-right {
+  text-align: right !important;
+}
+/**
+ * ========================= 文本大小写转换
+ */
+/* 文本转为小写 */
+.mdui-text-lowercase {
+  text-transform: lowercase !important;
+}
+/* 文本转为大写 */
+.mdui-text-uppercase {
+  text-transform: uppercase !important;
+}
+/* 文本转为单词的首字母大写 */
+.mdui-text-capitalize {
+  text-transform: capitalize !important;
+}
+/**
+ * ======================== 文本截断
+ */
+/* 文本截断 */
+.mdui-text-truncate {
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+/**
+ * ========================= 清除浮动
+ */
+/* 清除浮动 */
+.mdui-clearfix::before,
+.mdui-clearfix::after {
+  display: table;
+  content: ' ';
+}
+.mdui-clearfix::after {
+  clear: both;
+}
+/**
+ * ========================= 隐藏内容
+ */
+/* 隐藏元素 */
+.mdui-hidden,
+[hidden] {
+  display: none !important;
+}
+/* 使元素不可见 */
+.mdui-invisible {
+  visibility: hidden;
+}
+/* Responsive utilities 响应式工具
+   ========================================================================== */
+/* 在特定屏幕的特备上隐藏 */
+@media (max-width: 599.9px) {
+  .mdui-hidden-xs {
+    display: none !important;
+  }
+}
+@media (min-width: 600px) and (max-width: 1023.9px) {
+  .mdui-hidden-sm {
+    display: none !important;
+  }
+}
+@media (min-width: 1024px) and (max-width: 1439.9px) {
+  .mdui-hidden-md {
+    display: none !important;
+  }
+}
+@media (min-width: 1440px) and (max-width: 1919.9px) {
+  .mdui-hidden-lg {
+    display: none !important;
+  }
+}
+@media (min-width: 1920px) {
+  .mdui-hidden-xl {
+    display: none !important;
+  }
+}
+/* 在比特定屏幕小的设备上隐藏 */
+@media (max-width: 599.9px) {
+  .mdui-hidden-xs-down {
+    display: none !important;
+  }
+}
+@media (max-width: 1023.9px) {
+  .mdui-hidden-sm-down {
+    display: none !important;
+  }
+}
+@media (max-width: 1439.9px) {
+  .mdui-hidden-md-down {
+    display: none !important;
+  }
+}
+@media (max-width: 1919.9px) {
+  .mdui-hidden-lg-down {
+    display: none !important;
+  }
+}
+.mdui-hidden-xl-down {
+  display: none !important;
+}
+/* 在比特定屏幕大的设备上隐藏 */
+.mdui-hidden-xs-up {
+  display: none !important;
+}
+@media (min-width: 600px) {
+  .mdui-hidden-sm-up {
+    display: none !important;
+  }
+}
+@media (min-width: 1024px) {
+  .mdui-hidden-md-up {
+    display: none !important;
+  }
+}
+@media (min-width: 1440px) {
+  .mdui-hidden-lg-up {
+    display: none !important;
+  }
+}
+@media (min-width: 1920px) {
+  .mdui-hidden-xl-up {
+    display: none !important;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Icon 图标   ************
+ * =============================================================================
+ */
+.mdui-icon,
+.mdui-icon::before {
+  color: inherit;
+  font-weight: normal;
+  font-size: 24px;
+  /* Preferred icon size */
+  font-style: normal;
+  line-height: 1;
+  direction: ltr;
+  letter-spacing: normal;
+  white-space: nowrap;
+  text-transform: none;
+  vertical-align: middle;
+  word-wrap: normal;
+}
+.mdui-icon {
+  display: inline-block;
+  text-align: center;
+}
+.mdui-icon::before {
+  display: block !important;
+  width: 24px;
+  height: 24px;
+}
+/**
+ * =============================================================================
+ * ************   Material Icons   ************
+ * =============================================================================
+ *
+ * https://github.com/google/material-design-icons/
+ * v3.0.1
+ */
+@font-face {
+  font-weight: 400;
+  font-family: 'Material Icons';
+  font-style: normal;
+  src: local('Material Icons'), local('MaterialIcons-Regular'), url(../icons/material-icons/MaterialIcons-Regular.woff2) format('woff2'), url(../icons/material-icons/MaterialIcons-Regular.woff) format('woff');
+}
+.material-icons {
+  /* stylelint-disable-next-line */
+  font-family: 'Material Icons';
+  /* Support for all WebKit browsers. */
+  -webkit-font-smoothing: antialiased;
+  /* Support for Safari and Chrome. */
+  text-rendering: optimizeLegibility;
+  /* Support for Firefox. */
+  -moz-osx-font-smoothing: grayscale;
+  /* Support for IE. */
+  -webkit-font-feature-settings: 'liga';
+          font-feature-settings: 'liga';
+}
+/**
+ * =============================================================================
+ * ************   Media 媒体工具   ************
+ * =============================================================================
+ */
+/* 响应式图片和视频 */
+.mdui-img-fluid,
+.mdui-video-fluid {
+  display: block;
+  max-width: 100%;
+  height: auto;
+}
+/* 圆角图片 */
+.mdui-img-rounded {
+  border-radius: 2px;
+}
+/* 圆形图片 */
+.mdui-img-circle {
+  border-radius: 50%;
+}
+.mdui-video-container {
+  position: relative;
+  height: 0;
+  padding-bottom: 56.25%;
+  overflow: hidden;
+}
+.mdui-video-container iframe,
+.mdui-video-container object,
+.mdui-video-container embed {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+/**
+ * =============================================================================
+ * ************   Roboto 字体   ************
+ * =============================================================================
+ */
+@font-face {
+  font-weight: 100;
+  font-family: 'Roboto';
+  font-style: normal;
+  font-display: swap;
+  src: local('Roboto Thin'), local('Roboto-Thin'), url('../fonts/roboto/Roboto-Thin.woff2') format('woff2'), url('../fonts/roboto/Roboto-Thin.woff') format('woff');
+}
+@font-face {
+  font-weight: 100;
+  font-family: 'Roboto';
+  font-style: italic;
+  font-display: swap;
+  src: local('Roboto ThinItalic'), local('Roboto-ThinItalic'), url('../fonts/roboto/Roboto-ThinItalic.woff2') format('woff2'), url('../fonts/roboto/Roboto-ThinItalic.woff') format('woff');
+}
+@font-face {
+  font-weight: 300;
+  font-family: 'Roboto';
+  font-style: normal;
+  font-display: swap;
+  src: local('Roboto Light'), local('Roboto-Light'), url('../fonts/roboto/Roboto-Light.woff2') format('woff2'), url('../fonts/roboto/Roboto-Light.woff') format('woff');
+}
+@font-face {
+  font-weight: 300;
+  font-family: 'Roboto';
+  font-style: italic;
+  font-display: swap;
+  src: local('Roboto LightItalic'), local('Roboto-LightItalic'), url('../fonts/roboto/Roboto-LightItalic.woff2') format('woff2'), url('../fonts/roboto/Roboto-LightItalic.woff') format('woff');
+}
+@font-face {
+  font-weight: 400;
+  font-family: 'Roboto';
+  font-style: normal;
+  font-display: swap;
+  src: local('Roboto Regular'), local('Roboto-Regular'), url('../fonts/roboto/Roboto-Regular.woff2') format('woff2'), url('../fonts/roboto/Roboto-Regular.woff') format('woff');
+}
+@font-face {
+  font-weight: 400;
+  font-family: 'Roboto';
+  font-style: italic;
+  font-display: swap;
+  src: local('Roboto RegularItalic'), local('Roboto-RegularItalic'), url('../fonts/roboto/Roboto-RegularItalic.woff2') format('woff2'), url('../fonts/roboto/Roboto-RegularItalic.woff') format('woff');
+}
+@font-face {
+  font-weight: 500;
+  font-family: 'Roboto';
+  font-style: normal;
+  font-display: swap;
+  src: local('Roboto Medium'), local('Roboto-Medium'), url('../fonts/roboto/Roboto-Medium.woff2') format('woff2'), url('../fonts/roboto/Roboto-Medium.woff') format('woff');
+}
+@font-face {
+  font-weight: 500;
+  font-family: 'Roboto';
+  font-style: italic;
+  font-display: swap;
+  src: local('Roboto MediumItalic'), local('Roboto-MediumItalic'), url('../fonts/roboto/Roboto-MediumItalic.woff2') format('woff2'), url('../fonts/roboto/Roboto-MediumItalic.woff') format('woff');
+}
+@font-face {
+  font-weight: 700;
+  font-family: 'Roboto';
+  font-style: normal;
+  font-display: swap;
+  src: local('Roboto Bold'), local('Roboto-Bold'), url('../fonts/roboto/Roboto-Bold.woff2') format('woff2'), url('../fonts/roboto/Roboto-Bold.woff') format('woff');
+}
+@font-face {
+  font-weight: 700;
+  font-family: 'Roboto';
+  font-style: italic;
+  font-display: swap;
+  src: local('Roboto BoldItalic'), local('Roboto-BoldItalic'), url('../fonts/roboto/Roboto-BoldItalic.woff2') format('woff2'), url('../fonts/roboto/Roboto-BoldItalic.woff') format('woff');
+}
+@font-face {
+  font-weight: 900;
+  font-family: 'Roboto';
+  font-style: normal;
+  font-display: swap;
+  src: local('Roboto Black'), local('Roboto-Black'), url('../fonts/roboto/Roboto-Black.woff2') format('woff2'), url('../fonts/roboto/Roboto-Black.woff') format('woff');
+}
+@font-face {
+  font-weight: 900;
+  font-family: 'Roboto';
+  font-style: italic;
+  font-display: swap;
+  src: local('Roboto BlackItalic'), local('Roboto-BlackItalic'), url('../fonts/roboto/Roboto-BlackItalic.woff2') format('woff2'), url('../fonts/roboto/Roboto-BlackItalic.woff') format('woff');
+}
+/**
+ * =============================================================================
+ * ************   Typography 样式排版   ************
+ * =============================================================================
+ */
+/* .mdui-typo-display-4 */
+.mdui-typo-display-4,
+.mdui-typo-display-4-opacity {
+  font-weight: 300;
+  font-size: 112px;
+  letter-spacing: -0.04em;
+}
+.mdui-typo-display-4-opacity {
+  opacity: 0.54;
+}
+/* .mdui-typo-display-3 */
+.mdui-typo-display-3,
+.mdui-typo-display-3-opacity {
+  font-weight: 400;
+  font-size: 56px;
+  letter-spacing: -0.02em;
+}
+.mdui-typo-display-3-opacity {
+  opacity: 0.54;
+}
+/* .mdui-typo-display-2 */
+.mdui-typo-display-2,
+.mdui-typo-display-2-opacity {
+  font-weight: 400;
+  font-size: 45px;
+  letter-spacing: 0;
+}
+.mdui-typo-display-2-opacity {
+  opacity: 0.54;
+}
+/* .mdui-typo-display-1 */
+.mdui-typo-display-1,
+.mdui-typo-display-1-opacity {
+  font-weight: 400;
+  font-size: 34px;
+  letter-spacing: 0;
+}
+.mdui-typo-display-1-opacity {
+  opacity: 0.54;
+}
+/* .mdui-typo-headline */
+.mdui-typo-headline,
+.mdui-typo-headline-opacity {
+  font-weight: 400;
+  font-size: 24px;
+  -moz-osx-font-smoothing: grayscale;
+}
+.mdui-typo-headline-opacity {
+  opacity: 0.87;
+}
+/* .mdui-typo-title */
+.mdui-typo-title,
+.mdui-typo-title-opacity {
+  font-weight: 500;
+  font-size: 20px;
+  letter-spacing: 0.02em;
+}
+.mdui-typo-title-opacity {
+  opacity: 0.87;
+}
+.mdui-typo-subheading,
+.mdui-typo-subheading-opacity {
+  font-weight: 400;
+  font-size: 16px;
+  letter-spacing: 0.04em;
+}
+.mdui-typo-subheading-opacity {
+  opacity: 0.87;
+}
+.mdui-typo-body-2,
+.mdui-typo-body-2-opacity {
+  font-weight: 500;
+  font-size: 14px;
+  letter-spacing: 0.04em;
+}
+.mdui-typo-body-2-opacity {
+  opacity: 0.87;
+}
+.mdui-typo-body-1,
+.mdui-typo-body-1-opacity {
+  font-weight: 400;
+  font-size: 14px;
+  letter-spacing: 0.04em;
+}
+.mdui-typo-body-1-opacity {
+  opacity: 0.87;
+}
+.mdui-typo-caption,
+.mdui-typo-caption-opacity {
+  font-weight: 400;
+  font-size: 12px;
+  letter-spacing: 0.08em;
+}
+.mdui-typo-caption-opacity {
+  opacity: 0.54;
+}
+/**
+ * =============================================================================
+ * ************   Typography 文章排版   ************
+ * =============================================================================
+ */
+.mdui-typo {
+  line-height: 1.8;
+  word-wrap: break-word;
+  /* a */
+  /* small */
+  /* blockquote */
+  /* mark */
+  /* h1 - h6 */
+  /* code */
+  /* pre code */
+  /* abbr */
+  /* ins */
+  /* u */
+  /* del */
+  /* hr */
+  /* pre */
+  /* kbd */
+  /* ul / ol */
+  /* img, video */
+}
+.mdui-typo address,
+.mdui-typo caption,
+.mdui-typo cite,
+.mdui-typo code,
+.mdui-typo dfn,
+.mdui-typo th {
+  font-weight: 400;
+  font-style: normal;
+}
+.mdui-typo caption,
+.mdui-typo th {
+  text-align: left;
+}
+.mdui-typo q::before,
+.mdui-typo q::after {
+  content: '';
+}
+.mdui-typo pre,
+.mdui-typo code,
+.mdui-typo kbd,
+.mdui-typo samp,
+.mdui-typo pre tt {
+  font-family: Consolas, Courier, 'Courier New', monospace;
+}
+.mdui-typo figcaption {
+  color: rgba(0, 0, 0, 0.54);
+  font-size: 80%;
+}
+.mdui-typo [draggable],
+.mdui-typo [draggable="true"] {
+  cursor: move;
+}
+.mdui-typo [draggable="false"] {
+  cursor: inherit;
+}
+.mdui-typo p,
+.mdui-typo pre,
+.mdui-typo ul,
+.mdui-typo ol,
+.mdui-typo dl,
+.mdui-typo form,
+.mdui-typo hr,
+.mdui-typo figure,
+.mdui-typo table,
+.mdui-typo .mdui-table,
+.mdui-typo .mdui-table-fluid {
+  margin: 0 0 1.2em 0;
+}
+.mdui-typo p:last-child,
+.mdui-typo pre:last-child,
+.mdui-typo ul:last-child,
+.mdui-typo ol:last-child,
+.mdui-typo dl:last-child,
+.mdui-typo form:last-child,
+.mdui-typo hr:last-child,
+.mdui-typo figure:last-child,
+.mdui-typo table:last-child,
+.mdui-typo .mdui-table:last-child,
+.mdui-typo .mdui-table-fluid:last-child {
+  margin-bottom: 0;
+}
+.mdui-typo a {
+  color: #FF4081;
+  position: relative;
+  display: inline-block;
+  overflow: hidden;
+  text-decoration: none;
+  vertical-align: top;
+  outline: none;
+}
+.mdui-typo a::before {
+  position: absolute;
+  top: auto;
+  bottom: 1px;
+  left: 0;
+  width: 100%;
+  height: 1px;
+  background-color: #FF4081;
+  -webkit-transform: scaleX(0);
+          transform: scaleX(0);
+  -webkit-backface-visibility: hidden;
+          backface-visibility: hidden;
+  -webkit-transition: all 0.2s;
+  transition: all 0.2s;
+  content: ' ';
+}
+.mdui-typo a:hover::before,
+.mdui-typo a:focus::before {
+  -webkit-transform: scaleX(1);
+          transform: scaleX(1);
+}
+.mdui-typo small {
+  font-size: 80%;
+}
+.mdui-typo blockquote {
+  margin: 1em 3em 1em 2em;
+  padding-left: 1em;
+  font-weight: 400;
+  border-left: 4px solid rgba(0, 0, 0, 0.12);
+}
+@media only screen and (max-width: 599.9px) {
+  .mdui-typo blockquote {
+    margin: 1em 0;
+  }
+}
+.mdui-typo blockquote:last-child {
+  margin-bottom: 0;
+}
+.mdui-typo blockquote footer {
+  color: rgba(0, 0, 0, 0.54);
+  font-size: 86%;
+}
+.mdui-typo mark {
+  margin: 0 5px;
+  padding: 2px;
+  background: #fffdd1;
+  border-bottom: 1px solid #ffedce;
+}
+.mdui-typo h1,
+.mdui-typo h2,
+.mdui-typo h3,
+.mdui-typo h4,
+.mdui-typo h5,
+.mdui-typo h6 {
+  margin-top: 1.2em;
+  margin-bottom: 0.6em;
+  color: inherit;
+  font-weight: 400;
+  font-family: inherit;
+  line-height: 1.35;
+}
+.mdui-typo h1:last-child,
+.mdui-typo h2:last-child,
+.mdui-typo h3:last-child,
+.mdui-typo h4:last-child,
+.mdui-typo h5:last-child,
+.mdui-typo h6:last-child {
+  margin-bottom: 0;
+}
+.mdui-typo h1 small,
+.mdui-typo h2 small,
+.mdui-typo h3 small,
+.mdui-typo h4 small,
+.mdui-typo h5 small,
+.mdui-typo h6 small {
+  color: rgba(0, 0, 0, 0.54);
+  font-weight: 400;
+  font-size: 65%;
+  line-height: 1;
+}
+.mdui-typo h1 {
+  font-size: 2em;
+}
+.mdui-typo h2 {
+  font-size: 1.8em;
+}
+.mdui-typo h3 {
+  font-size: 1.6em;
+}
+.mdui-typo h4 {
+  font-size: 1.4em;
+}
+.mdui-typo h5 {
+  font-size: 1.2em;
+}
+.mdui-typo h6 {
+  font-size: 1.1em;
+}
+.mdui-typo code {
+  padding: 2px 6px;
+  color: #c7254e;
+  background-color: #f7f7f9;
+  border-radius: 2px;
+}
+.mdui-typo pre code {
+  padding: 0;
+  color: inherit;
+  font-size: inherit;
+  line-height: 1.7;
+  background-color: transparent;
+  border-radius: 0;
+}
+.mdui-typo abbr[title] {
+  text-decoration: none;
+  border-bottom: 1px dotted;
+  cursor: help;
+}
+.mdui-typo ins {
+  text-decoration: none;
+  border-bottom: 1px solid ;
+}
+.mdui-typo u {
+  text-decoration: none;
+  border-bottom: 1px solid;
+}
+.mdui-typo del {
+  text-decoration: line-through;
+}
+.mdui-typo hr {
+  height: 10px;
+  margin-bottom: 0.8em;
+  border: none;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
+}
+.mdui-typo pre {
+  padding: 12px 16px;
+  overflow-x: auto;
+  border: 1px solid rgba(0, 0, 0, 0.12);
+  border-radius: 2px;
+  -webkit-overflow-scrolling: touch;
+}
+.mdui-typo kbd {
+  padding: 2px 6px;
+  color: #fff;
+  font-size: 90%;
+  background-color: #333;
+  border-radius: 2px;
+}
+.mdui-typo ul {
+  padding-left: 2em;
+  list-style: disc;
+}
+.mdui-typo ol {
+  padding-left: 2em;
+  list-style: decimal;
+}
+.mdui-typo li ul,
+.mdui-typo li ol {
+  margin: 0.8em 0;
+}
+.mdui-typo li ul {
+  list-style: circle;
+}
+.mdui-typo img,
+.mdui-typo video {
+  max-width: 100%;
+}
+.mdui-typo figure {
+  text-align: center;
+}
+.mdui-typo figure figcaption {
+  margin-top: 8px;
+  color: #999;
+  font-size: 14px;
+}
+.mdui-typo figure figcaption:empty::before {
+  z-index: -1;
+  color: #bfbfbf;
+  cursor: text;
+  content: attr(placeholder);
+}
+/**
+ * =============================================================================
+ * ************   Typo 强调色   ************
+ * =============================================================================
+ */
+.mdui-theme-accent-amber .mdui-typo a {
+  color: #FFD740;
+}
+.mdui-theme-accent-amber .mdui-typo a::before {
+  background-color: #FFD740;
+}
+.mdui-theme-accent-blue .mdui-typo a {
+  color: #448AFF;
+}
+.mdui-theme-accent-blue .mdui-typo a::before {
+  background-color: #448AFF;
+}
+.mdui-theme-accent-cyan .mdui-typo a {
+  color: #18FFFF;
+}
+.mdui-theme-accent-cyan .mdui-typo a::before {
+  background-color: #18FFFF;
+}
+.mdui-theme-accent-deep-orange .mdui-typo a {
+  color: #FF6E40;
+}
+.mdui-theme-accent-deep-orange .mdui-typo a::before {
+  background-color: #FF6E40;
+}
+.mdui-theme-accent-deep-purple .mdui-typo a {
+  color: #7C4DFF;
+}
+.mdui-theme-accent-deep-purple .mdui-typo a::before {
+  background-color: #7C4DFF;
+}
+.mdui-theme-accent-green .mdui-typo a {
+  color: #69F0AE;
+}
+.mdui-theme-accent-green .mdui-typo a::before {
+  background-color: #69F0AE;
+}
+.mdui-theme-accent-indigo .mdui-typo a {
+  color: #536DFE;
+}
+.mdui-theme-accent-indigo .mdui-typo a::before {
+  background-color: #536DFE;
+}
+.mdui-theme-accent-light-blue .mdui-typo a {
+  color: #40C4FF;
+}
+.mdui-theme-accent-light-blue .mdui-typo a::before {
+  background-color: #40C4FF;
+}
+.mdui-theme-accent-light-green .mdui-typo a {
+  color: #B2FF59;
+}
+.mdui-theme-accent-light-green .mdui-typo a::before {
+  background-color: #B2FF59;
+}
+.mdui-theme-accent-lime .mdui-typo a {
+  color: #EEFF41;
+}
+.mdui-theme-accent-lime .mdui-typo a::before {
+  background-color: #EEFF41;
+}
+.mdui-theme-accent-orange .mdui-typo a {
+  color: #FFAB40;
+}
+.mdui-theme-accent-orange .mdui-typo a::before {
+  background-color: #FFAB40;
+}
+.mdui-theme-accent-pink .mdui-typo a {
+  color: #FF4081;
+}
+.mdui-theme-accent-pink .mdui-typo a::before {
+  background-color: #FF4081;
+}
+.mdui-theme-accent-purple .mdui-typo a {
+  color: #E040FB;
+}
+.mdui-theme-accent-purple .mdui-typo a::before {
+  background-color: #E040FB;
+}
+.mdui-theme-accent-red .mdui-typo a {
+  color: #FF5252;
+}
+.mdui-theme-accent-red .mdui-typo a::before {
+  background-color: #FF5252;
+}
+.mdui-theme-accent-teal .mdui-typo a {
+  color: #64FFDA;
+}
+.mdui-theme-accent-teal .mdui-typo a::before {
+  background-color: #64FFDA;
+}
+.mdui-theme-accent-yellow .mdui-typo a {
+  color: #FFFF00;
+}
+.mdui-theme-accent-yellow .mdui-typo a::before {
+  background-color: #FFFF00;
+}
+/**
+ * =============================================================================
+ * ************   Typo dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-typo blockquote {
+  border-left-color: rgba(255, 255, 255, 0.12);
+}
+.mdui-theme-layout-dark .mdui-typo blockquote footer {
+  color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-typo figcaption {
+  color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-typo mark {
+  background: #aaa;
+  border-bottom-color: #bbb;
+}
+.mdui-theme-layout-dark .mdui-typo h1 small,
+.mdui-theme-layout-dark .mdui-typo h2 small,
+.mdui-theme-layout-dark .mdui-typo h3 small,
+.mdui-theme-layout-dark .mdui-typo h4 small,
+.mdui-theme-layout-dark .mdui-typo h5 small,
+.mdui-theme-layout-dark .mdui-typo h6 small {
+  color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-typo code {
+  color: #FFCDD2;
+  background-color: #424242;
+}
+.mdui-theme-layout-dark .mdui-typo pre {
+  background: #424242;
+  border-color: rgba(255, 255, 255, 0.12);
+}
+.mdui-theme-layout-dark .mdui-typo kbd {
+  background: #424242;
+}
+.mdui-theme-layout-dark .mdui-typo hr {
+  border-color: rgba(255, 255, 255, 0.12);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-typo blockquote {
+    border-left-color: rgba(255, 255, 255, 0.12);
+  }
+  .mdui-theme-layout-auto .mdui-typo blockquote footer {
+    color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-typo figcaption {
+    color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-typo mark {
+    background: #aaa;
+    border-bottom-color: #bbb;
+  }
+  .mdui-theme-layout-auto .mdui-typo h1 small,
+  .mdui-theme-layout-auto .mdui-typo h2 small,
+  .mdui-theme-layout-auto .mdui-typo h3 small,
+  .mdui-theme-layout-auto .mdui-typo h4 small,
+  .mdui-theme-layout-auto .mdui-typo h5 small,
+  .mdui-theme-layout-auto .mdui-typo h6 small {
+    color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-typo code {
+    color: #FFCDD2;
+    background-color: #424242;
+  }
+  .mdui-theme-layout-auto .mdui-typo pre {
+    background: #424242;
+    border-color: rgba(255, 255, 255, 0.12);
+  }
+  .mdui-theme-layout-auto .mdui-typo kbd {
+    background: #424242;
+  }
+  .mdui-theme-layout-auto .mdui-typo hr {
+    border-color: rgba(255, 255, 255, 0.12);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Grid 网格系统   ************
+ * =============================================================================
+ */
+.mdui-container,
+.mdui-container-fluid {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  margin-right: auto;
+  margin-left: auto;
+  padding-right: 8px;
+  padding-left: 8px;
+}
+.mdui-container::after,
+.mdui-container-fluid::after {
+  display: table;
+  clear: both;
+  content: '';
+}
+.mdui-container {
+  width: 96%;
+  max-width: 1280px;
+}
+@media (min-width: 600px) {
+  .mdui-container {
+    width: 94%;
+  }
+}
+@media (min-width: 1024px) {
+  .mdui-container {
+    width: 92%;
+  }
+}
+.mdui-row,
+[class*="mdui-row-"] {
+  margin-right: -8px;
+  margin-left: -8px;
+}
+.mdui-row::after,
+[class*="mdui-row-"]::after {
+  display: table;
+  clear: both;
+  content: '';
+}
+[class*="mdui-col-xs-"],
+[class*="mdui-col-sm-"],
+[class*="mdui-col-md-"],
+[class*="mdui-col-lg-"],
+[class*="mdui-col-xl-"],
+.mdui-col {
+  position: relative;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  min-height: 1px;
+  padding-right: 8px;
+  padding-left: 8px;
+}
+/* 取消列间距 */
+.mdui-row-gapless .mdui-col,
+.mdui-row-gapless [class*="mdui-col-xs-"],
+.mdui-row-gapless [class*="mdui-col-sm-"],
+.mdui-row-gapless [class*="mdui-col-md-"],
+.mdui-row-gapless [class*="mdui-col-lg-"],
+.mdui-row-gapless [class*="mdui-col-xl-"] {
+  padding-right: 0;
+  padding-left: 0;
+}
+.mdui-row-gapless .mdui-row,
+.mdui-row-gapless [class*="mdui-row-"] {
+  margin-right: 0;
+  margin-left: 0;
+}
+.mdui-col-xs-1 {
+  float: left;
+  width: 8.333333%;
+}
+.mdui-col-offset-xs-1 {
+  margin-left: 8.333333%;
+}
+.mdui-row-xs-1 .mdui-col {
+  float: left;
+  width: 100%;
+}
+.mdui-col-xs-2 {
+  float: left;
+  width: 16.666667%;
+}
+.mdui-col-offset-xs-2 {
+  margin-left: 16.666667%;
+}
+.mdui-row-xs-2 .mdui-col {
+  float: left;
+  width: 50%;
+}
+.mdui-col-xs-3 {
+  float: left;
+  width: 25%;
+}
+.mdui-col-offset-xs-3 {
+  margin-left: 25%;
+}
+.mdui-row-xs-3 .mdui-col {
+  float: left;
+  width: 33.333333%;
+}
+.mdui-col-xs-4 {
+  float: left;
+  width: 33.333333%;
+}
+.mdui-col-offset-xs-4 {
+  margin-left: 33.333333%;
+}
+.mdui-row-xs-4 .mdui-col {
+  float: left;
+  width: 25%;
+}
+.mdui-col-xs-5 {
+  float: left;
+  width: 41.666667%;
+}
+.mdui-col-offset-xs-5 {
+  margin-left: 41.666667%;
+}
+.mdui-row-xs-5 .mdui-col {
+  float: left;
+  width: 20%;
+}
+.mdui-col-xs-6 {
+  float: left;
+  width: 50%;
+}
+.mdui-col-offset-xs-6 {
+  margin-left: 50%;
+}
+.mdui-row-xs-6 .mdui-col {
+  float: left;
+  width: 16.666667%;
+}
+.mdui-col-xs-7 {
+  float: left;
+  width: 58.333333%;
+}
+.mdui-col-offset-xs-7 {
+  margin-left: 58.333333%;
+}
+.mdui-row-xs-7 .mdui-col {
+  float: left;
+  width: 14.285714%;
+}
+.mdui-col-xs-8 {
+  float: left;
+  width: 66.666667%;
+}
+.mdui-col-offset-xs-8 {
+  margin-left: 66.666667%;
+}
+.mdui-row-xs-8 .mdui-col {
+  float: left;
+  width: 12.5%;
+}
+.mdui-col-xs-9 {
+  float: left;
+  width: 75%;
+}
+.mdui-col-offset-xs-9 {
+  margin-left: 75%;
+}
+.mdui-row-xs-9 .mdui-col {
+  float: left;
+  width: 11.111111%;
+}
+.mdui-col-xs-10 {
+  float: left;
+  width: 83.333333%;
+}
+.mdui-col-offset-xs-10 {
+  margin-left: 83.333333%;
+}
+.mdui-row-xs-10 .mdui-col {
+  float: left;
+  width: 10%;
+}
+.mdui-col-xs-11 {
+  float: left;
+  width: 91.666667%;
+}
+.mdui-col-offset-xs-11 {
+  margin-left: 91.666667%;
+}
+.mdui-row-xs-11 .mdui-col {
+  float: left;
+  width: 9.090909%;
+}
+.mdui-col-xs-12 {
+  float: left;
+  width: 100%;
+}
+.mdui-col-offset-xs-12 {
+  margin-left: 100%;
+}
+.mdui-row-xs-12 .mdui-col {
+  float: left;
+  width: 8.333333%;
+}
+@media (min-width: 600px) {
+  .mdui-col-sm-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .mdui-col-offset-sm-1 {
+    margin-left: 8.333333%;
+  }
+  .mdui-row-sm-1 .mdui-col {
+    float: left;
+    width: 100%;
+  }
+  .mdui-col-sm-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .mdui-col-offset-sm-2 {
+    margin-left: 16.666667%;
+  }
+  .mdui-row-sm-2 .mdui-col {
+    float: left;
+    width: 50%;
+  }
+  .mdui-col-sm-3 {
+    float: left;
+    width: 25%;
+  }
+  .mdui-col-offset-sm-3 {
+    margin-left: 25%;
+  }
+  .mdui-row-sm-3 .mdui-col {
+    float: left;
+    width: 33.333333%;
+  }
+  .mdui-col-sm-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .mdui-col-offset-sm-4 {
+    margin-left: 33.333333%;
+  }
+  .mdui-row-sm-4 .mdui-col {
+    float: left;
+    width: 25%;
+  }
+  .mdui-col-sm-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .mdui-col-offset-sm-5 {
+    margin-left: 41.666667%;
+  }
+  .mdui-row-sm-5 .mdui-col {
+    float: left;
+    width: 20%;
+  }
+  .mdui-col-sm-6 {
+    float: left;
+    width: 50%;
+  }
+  .mdui-col-offset-sm-6 {
+    margin-left: 50%;
+  }
+  .mdui-row-sm-6 .mdui-col {
+    float: left;
+    width: 16.666667%;
+  }
+  .mdui-col-sm-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .mdui-col-offset-sm-7 {
+    margin-left: 58.333333%;
+  }
+  .mdui-row-sm-7 .mdui-col {
+    float: left;
+    width: 14.285714%;
+  }
+  .mdui-col-sm-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .mdui-col-offset-sm-8 {
+    margin-left: 66.666667%;
+  }
+  .mdui-row-sm-8 .mdui-col {
+    float: left;
+    width: 12.5%;
+  }
+  .mdui-col-sm-9 {
+    float: left;
+    width: 75%;
+  }
+  .mdui-col-offset-sm-9 {
+    margin-left: 75%;
+  }
+  .mdui-row-sm-9 .mdui-col {
+    float: left;
+    width: 11.111111%;
+  }
+  .mdui-col-sm-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .mdui-col-offset-sm-10 {
+    margin-left: 83.333333%;
+  }
+  .mdui-row-sm-10 .mdui-col {
+    float: left;
+    width: 10%;
+  }
+  .mdui-col-sm-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .mdui-col-offset-sm-11 {
+    margin-left: 91.666667%;
+  }
+  .mdui-row-sm-11 .mdui-col {
+    float: left;
+    width: 9.090909%;
+  }
+  .mdui-col-sm-12 {
+    float: left;
+    width: 100%;
+  }
+  .mdui-col-offset-sm-12 {
+    margin-left: 100%;
+  }
+  .mdui-row-sm-12 .mdui-col {
+    float: left;
+    width: 8.333333%;
+  }
+}
+@media (min-width: 1024px) {
+  .mdui-col-md-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .mdui-col-offset-md-1 {
+    margin-left: 8.333333%;
+  }
+  .mdui-row-md-1 .mdui-col {
+    float: left;
+    width: 100%;
+  }
+  .mdui-col-md-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .mdui-col-offset-md-2 {
+    margin-left: 16.666667%;
+  }
+  .mdui-row-md-2 .mdui-col {
+    float: left;
+    width: 50%;
+  }
+  .mdui-col-md-3 {
+    float: left;
+    width: 25%;
+  }
+  .mdui-col-offset-md-3 {
+    margin-left: 25%;
+  }
+  .mdui-row-md-3 .mdui-col {
+    float: left;
+    width: 33.333333%;
+  }
+  .mdui-col-md-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .mdui-col-offset-md-4 {
+    margin-left: 33.333333%;
+  }
+  .mdui-row-md-4 .mdui-col {
+    float: left;
+    width: 25%;
+  }
+  .mdui-col-md-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .mdui-col-offset-md-5 {
+    margin-left: 41.666667%;
+  }
+  .mdui-row-md-5 .mdui-col {
+    float: left;
+    width: 20%;
+  }
+  .mdui-col-md-6 {
+    float: left;
+    width: 50%;
+  }
+  .mdui-col-offset-md-6 {
+    margin-left: 50%;
+  }
+  .mdui-row-md-6 .mdui-col {
+    float: left;
+    width: 16.666667%;
+  }
+  .mdui-col-md-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .mdui-col-offset-md-7 {
+    margin-left: 58.333333%;
+  }
+  .mdui-row-md-7 .mdui-col {
+    float: left;
+    width: 14.285714%;
+  }
+  .mdui-col-md-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .mdui-col-offset-md-8 {
+    margin-left: 66.666667%;
+  }
+  .mdui-row-md-8 .mdui-col {
+    float: left;
+    width: 12.5%;
+  }
+  .mdui-col-md-9 {
+    float: left;
+    width: 75%;
+  }
+  .mdui-col-offset-md-9 {
+    margin-left: 75%;
+  }
+  .mdui-row-md-9 .mdui-col {
+    float: left;
+    width: 11.111111%;
+  }
+  .mdui-col-md-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .mdui-col-offset-md-10 {
+    margin-left: 83.333333%;
+  }
+  .mdui-row-md-10 .mdui-col {
+    float: left;
+    width: 10%;
+  }
+  .mdui-col-md-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .mdui-col-offset-md-11 {
+    margin-left: 91.666667%;
+  }
+  .mdui-row-md-11 .mdui-col {
+    float: left;
+    width: 9.090909%;
+  }
+  .mdui-col-md-12 {
+    float: left;
+    width: 100%;
+  }
+  .mdui-col-offset-md-12 {
+    margin-left: 100%;
+  }
+  .mdui-row-md-12 .mdui-col {
+    float: left;
+    width: 8.333333%;
+  }
+}
+@media (min-width: 1440px) {
+  .mdui-col-lg-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .mdui-col-offset-lg-1 {
+    margin-left: 8.333333%;
+  }
+  .mdui-row-lg-1 .mdui-col {
+    float: left;
+    width: 100%;
+  }
+  .mdui-col-lg-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .mdui-col-offset-lg-2 {
+    margin-left: 16.666667%;
+  }
+  .mdui-row-lg-2 .mdui-col {
+    float: left;
+    width: 50%;
+  }
+  .mdui-col-lg-3 {
+    float: left;
+    width: 25%;
+  }
+  .mdui-col-offset-lg-3 {
+    margin-left: 25%;
+  }
+  .mdui-row-lg-3 .mdui-col {
+    float: left;
+    width: 33.333333%;
+  }
+  .mdui-col-lg-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .mdui-col-offset-lg-4 {
+    margin-left: 33.333333%;
+  }
+  .mdui-row-lg-4 .mdui-col {
+    float: left;
+    width: 25%;
+  }
+  .mdui-col-lg-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .mdui-col-offset-lg-5 {
+    margin-left: 41.666667%;
+  }
+  .mdui-row-lg-5 .mdui-col {
+    float: left;
+    width: 20%;
+  }
+  .mdui-col-lg-6 {
+    float: left;
+    width: 50%;
+  }
+  .mdui-col-offset-lg-6 {
+    margin-left: 50%;
+  }
+  .mdui-row-lg-6 .mdui-col {
+    float: left;
+    width: 16.666667%;
+  }
+  .mdui-col-lg-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .mdui-col-offset-lg-7 {
+    margin-left: 58.333333%;
+  }
+  .mdui-row-lg-7 .mdui-col {
+    float: left;
+    width: 14.285714%;
+  }
+  .mdui-col-lg-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .mdui-col-offset-lg-8 {
+    margin-left: 66.666667%;
+  }
+  .mdui-row-lg-8 .mdui-col {
+    float: left;
+    width: 12.5%;
+  }
+  .mdui-col-lg-9 {
+    float: left;
+    width: 75%;
+  }
+  .mdui-col-offset-lg-9 {
+    margin-left: 75%;
+  }
+  .mdui-row-lg-9 .mdui-col {
+    float: left;
+    width: 11.111111%;
+  }
+  .mdui-col-lg-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .mdui-col-offset-lg-10 {
+    margin-left: 83.333333%;
+  }
+  .mdui-row-lg-10 .mdui-col {
+    float: left;
+    width: 10%;
+  }
+  .mdui-col-lg-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .mdui-col-offset-lg-11 {
+    margin-left: 91.666667%;
+  }
+  .mdui-row-lg-11 .mdui-col {
+    float: left;
+    width: 9.090909%;
+  }
+  .mdui-col-lg-12 {
+    float: left;
+    width: 100%;
+  }
+  .mdui-col-offset-lg-12 {
+    margin-left: 100%;
+  }
+  .mdui-row-lg-12 .mdui-col {
+    float: left;
+    width: 8.333333%;
+  }
+}
+@media (min-width: 1920px) {
+  .mdui-col-xl-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .mdui-col-offset-xl-1 {
+    margin-left: 8.333333%;
+  }
+  .mdui-row-xl-1 .mdui-col {
+    float: left;
+    width: 100%;
+  }
+  .mdui-col-xl-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .mdui-col-offset-xl-2 {
+    margin-left: 16.666667%;
+  }
+  .mdui-row-xl-2 .mdui-col {
+    float: left;
+    width: 50%;
+  }
+  .mdui-col-xl-3 {
+    float: left;
+    width: 25%;
+  }
+  .mdui-col-offset-xl-3 {
+    margin-left: 25%;
+  }
+  .mdui-row-xl-3 .mdui-col {
+    float: left;
+    width: 33.333333%;
+  }
+  .mdui-col-xl-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .mdui-col-offset-xl-4 {
+    margin-left: 33.333333%;
+  }
+  .mdui-row-xl-4 .mdui-col {
+    float: left;
+    width: 25%;
+  }
+  .mdui-col-xl-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .mdui-col-offset-xl-5 {
+    margin-left: 41.666667%;
+  }
+  .mdui-row-xl-5 .mdui-col {
+    float: left;
+    width: 20%;
+  }
+  .mdui-col-xl-6 {
+    float: left;
+    width: 50%;
+  }
+  .mdui-col-offset-xl-6 {
+    margin-left: 50%;
+  }
+  .mdui-row-xl-6 .mdui-col {
+    float: left;
+    width: 16.666667%;
+  }
+  .mdui-col-xl-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .mdui-col-offset-xl-7 {
+    margin-left: 58.333333%;
+  }
+  .mdui-row-xl-7 .mdui-col {
+    float: left;
+    width: 14.285714%;
+  }
+  .mdui-col-xl-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .mdui-col-offset-xl-8 {
+    margin-left: 66.666667%;
+  }
+  .mdui-row-xl-8 .mdui-col {
+    float: left;
+    width: 12.5%;
+  }
+  .mdui-col-xl-9 {
+    float: left;
+    width: 75%;
+  }
+  .mdui-col-offset-xl-9 {
+    margin-left: 75%;
+  }
+  .mdui-row-xl-9 .mdui-col {
+    float: left;
+    width: 11.111111%;
+  }
+  .mdui-col-xl-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .mdui-col-offset-xl-10 {
+    margin-left: 83.333333%;
+  }
+  .mdui-row-xl-10 .mdui-col {
+    float: left;
+    width: 10%;
+  }
+  .mdui-col-xl-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .mdui-col-offset-xl-11 {
+    margin-left: 91.666667%;
+  }
+  .mdui-row-xl-11 .mdui-col {
+    float: left;
+    width: 9.090909%;
+  }
+  .mdui-col-xl-12 {
+    float: left;
+    width: 100%;
+  }
+  .mdui-col-offset-xl-12 {
+    margin-left: 100%;
+  }
+  .mdui-row-xl-12 .mdui-col {
+    float: left;
+    width: 8.333333%;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Shadow 阴影   ************
+ * =============================================================================
+ */
+.mdui-shadow-0 {
+  -webkit-box-shadow: none !important;
+          box-shadow: none !important;
+}
+.mdui-shadow-1 {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-2 {
+  -webkit-box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-3 {
+  -webkit-box-shadow: 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 1px 8px 0 rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 1px 8px 0 rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-4 {
+  -webkit-box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-5 {
+  -webkit-box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 5px 8px 0 rgba(0, 0, 0, 0.14), 0 1px 14px 0 rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 5px 8px 0 rgba(0, 0, 0, 0.14), 0 1px 14px 0 rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-6 {
+  -webkit-box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-7 {
+  -webkit-box-shadow: 0 4px 5px -2px rgba(0, 0, 0, 0.2), 0 7px 10px 1px rgba(0, 0, 0, 0.14), 0 2px 16px 1px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 4px 5px -2px rgba(0, 0, 0, 0.2), 0 7px 10px 1px rgba(0, 0, 0, 0.14), 0 2px 16px 1px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-8 {
+  -webkit-box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-9 {
+  -webkit-box-shadow: 0 5px 6px -3px rgba(0, 0, 0, 0.2), 0 9px 12px 1px rgba(0, 0, 0, 0.14), 0 3px 16px 2px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 5px 6px -3px rgba(0, 0, 0, 0.2), 0 9px 12px 1px rgba(0, 0, 0, 0.14), 0 3px 16px 2px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-10 {
+  -webkit-box-shadow: 0 6px 6px -3px rgba(0, 0, 0, 0.2), 0 10px 14px 1px rgba(0, 0, 0, 0.14), 0 4px 18px 3px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 6px 6px -3px rgba(0, 0, 0, 0.2), 0 10px 14px 1px rgba(0, 0, 0, 0.14), 0 4px 18px 3px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-11 {
+  -webkit-box-shadow: 0 6px 7px -4px rgba(0, 0, 0, 0.2), 0 11px 15px 1px rgba(0, 0, 0, 0.14), 0 4px 20px 3px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 6px 7px -4px rgba(0, 0, 0, 0.2), 0 11px 15px 1px rgba(0, 0, 0, 0.14), 0 4px 20px 3px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-12 {
+  -webkit-box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 12px 17px 2px rgba(0, 0, 0, 0.14), 0 5px 22px 4px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 12px 17px 2px rgba(0, 0, 0, 0.14), 0 5px 22px 4px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-13 {
+  -webkit-box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 13px 19px 2px rgba(0, 0, 0, 0.14), 0 5px 24px 4px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 13px 19px 2px rgba(0, 0, 0, 0.14), 0 5px 24px 4px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-14 {
+  -webkit-box-shadow: 0 7px 9px -4px rgba(0, 0, 0, 0.2), 0 14px 21px 2px rgba(0, 0, 0, 0.14), 0 5px 26px 4px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 7px 9px -4px rgba(0, 0, 0, 0.2), 0 14px 21px 2px rgba(0, 0, 0, 0.14), 0 5px 26px 4px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-15 {
+  -webkit-box-shadow: 0 8px 9px -5px rgba(0, 0, 0, 0.2), 0 15px 22px 2px rgba(0, 0, 0, 0.14), 0 6px 28px 5px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 8px 9px -5px rgba(0, 0, 0, 0.2), 0 15px 22px 2px rgba(0, 0, 0, 0.14), 0 6px 28px 5px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-16 {
+  -webkit-box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-17 {
+  -webkit-box-shadow: 0 8px 11px -5px rgba(0, 0, 0, 0.2), 0 17px 26px 2px rgba(0, 0, 0, 0.14), 0 6px 32px 5px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 8px 11px -5px rgba(0, 0, 0, 0.2), 0 17px 26px 2px rgba(0, 0, 0, 0.14), 0 6px 32px 5px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-18 {
+  -webkit-box-shadow: 0 9px 11px -5px rgba(0, 0, 0, 0.2), 0 18px 28px 2px rgba(0, 0, 0, 0.14), 0 7px 34px 6px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 9px 11px -5px rgba(0, 0, 0, 0.2), 0 18px 28px 2px rgba(0, 0, 0, 0.14), 0 7px 34px 6px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-19 {
+  -webkit-box-shadow: 0 9px 12px -6px rgba(0, 0, 0, 0.2), 0 19px 29px 2px rgba(0, 0, 0, 0.14), 0 7px 36px 6px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 9px 12px -6px rgba(0, 0, 0, 0.2), 0 19px 29px 2px rgba(0, 0, 0, 0.14), 0 7px 36px 6px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-20 {
+  -webkit-box-shadow: 0 10px 13px -6px rgba(0, 0, 0, 0.2), 0 20px 31px 3px rgba(0, 0, 0, 0.14), 0 8px 38px 7px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 10px 13px -6px rgba(0, 0, 0, 0.2), 0 20px 31px 3px rgba(0, 0, 0, 0.14), 0 8px 38px 7px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-21 {
+  -webkit-box-shadow: 0 10px 13px -6px rgba(0, 0, 0, 0.2), 0 21px 33px 3px rgba(0, 0, 0, 0.14), 0 8px 40px 7px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 10px 13px -6px rgba(0, 0, 0, 0.2), 0 21px 33px 3px rgba(0, 0, 0, 0.14), 0 8px 40px 7px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-22 {
+  -webkit-box-shadow: 0 10px 14px -6px rgba(0, 0, 0, 0.2), 0 22px 35px 3px rgba(0, 0, 0, 0.14), 0 8px 42px 7px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 10px 14px -6px rgba(0, 0, 0, 0.2), 0 22px 35px 3px rgba(0, 0, 0, 0.14), 0 8px 42px 7px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-23 {
+  -webkit-box-shadow: 0 11px 14px -7px rgba(0, 0, 0, 0.2), 0 23px 36px 3px rgba(0, 0, 0, 0.14), 0 9px 44px 8px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 11px 14px -7px rgba(0, 0, 0, 0.2), 0 23px 36px 3px rgba(0, 0, 0, 0.14), 0 9px 44px 8px rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-shadow-24 {
+  -webkit-box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2), 0 24px 38px 3px rgba(0, 0, 0, 0.14), 0 9px 46px 8px rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2), 0 24px 38px 3px rgba(0, 0, 0, 0.14), 0 9px 46px 8px rgba(0, 0, 0, 0.12) !important;
+}
+/* 鼠标悬浮时加深阴影 */
+.mdui-hoverable {
+  -webkit-transition: -webkit-box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: -webkit-box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: box-shadow;
+}
+.mdui-hoverable:hover,
+.mdui-hoverable:focus {
+  -webkit-box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+}
+/**
+ * =============================================================================
+ * ************   Headroom   ************
+ * =============================================================================
+ */
+.mdui-headroom {
+  -webkit-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
+}
+/* 固定在顶部时 */
+.mdui-headroom-pinned-top {
+  -webkit-transform: translate3d(0, 0, 0) !important;
+          transform: translate3d(0, 0, 0) !important;
+}
+/* 在顶部隐藏时 */
+.mdui-headroom-unpinned-top {
+  -webkit-transform: translate3d(0, -100%, 0) !important;
+          transform: translate3d(0, -100%, 0) !important;
+  -webkit-box-shadow: none !important;
+          box-shadow: none !important;
+}
+/* 固定在底部时 */
+.mdui-headroom-pinned-down {
+  -webkit-transform: translate3d(0, 0, 0) !important;
+          transform: translate3d(0, 0, 0) !important;
+}
+/* 在底部隐藏时 */
+.mdui-headroom-unpinned-down {
+  -webkit-transform: translate3d(0, 100%, 0) !important;
+          transform: translate3d(0, 100%, 0) !important;
+  -webkit-box-shadow: none !important;
+          box-shadow: none !important;
+}
+/* 固定应用栏中的工具栏 */
+.mdui-headroom-pinned-toolbar {
+  -webkit-transform: translate3d(0, 0, 0) !important;
+          transform: translate3d(0, 0, 0) !important;
+}
+/* 隐藏应用栏中的工具栏 */
+.mdui-headroom-unpinned-toolbar {
+  -webkit-transform: translate3d(0, -56px, 0) !important;
+          transform: translate3d(0, -56px, 0) !important;
+}
+@media (min-width: 600px) {
+  .mdui-headroom-unpinned-toolbar {
+    -webkit-transform: translate3d(0, -64px, 0) !important;
+            transform: translate3d(0, -64px, 0) !important;
+  }
+}
+@media (orientation: landscape) and (max-width: 959.9px) {
+  .mdui-headroom-unpinned-toolbar {
+    -webkit-transform: translate3d(0, -48px, 0) !important;
+            transform: translate3d(0, -48px, 0) !important;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Collapse 折叠插件   ************
+ * =============================================================================
+ */
+.mdui-collapse-item-header .mdui-collapse-item-arrow,
+.mdui-collapse-item-header.mdui-collapse-item-arrow {
+  -webkit-transform: rotate(0);
+          transform: rotate(0);
+  -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: -webkit-transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), -webkit-transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: transform;
+}
+.mdui-collapse-item-body {
+  height: 0;
+  margin-top: 0;
+  margin-bottom: 0;
+  padding-top: 0;
+  padding-bottom: 0;
+  overflow: hidden;
+  -webkit-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: height;
+}
+.mdui-collapse-item-body .mdui-list-item {
+  padding-left: 72px;
+}
+.mdui-collapse-item-open > .mdui-collapse-item-header .mdui-collapse-item-arrow,
+.mdui-collapse-item-open > .mdui-collapse-item-header.mdui-collapse-item-arrow {
+  -webkit-transform: rotate(180deg);
+          transform: rotate(180deg);
+}
+.mdui-collapse-item-open > .mdui-collapse-item-body {
+  height: auto;
+}
+/**
+ * =============================================================================
+ * ************   Expansion panel 可扩展面板   ************
+ * =============================================================================
+ */
+/* 可扩展面板 */
+.mdui-panel {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 100%;
+}
+/* 面板项 */
+.mdui-panel-item {
+  color: rgba(0, 0, 0, 0.87);
+  background-color: #fff;
+  -webkit-transition: margin 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: margin 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: margin;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
+  -webkit-box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+}
+.mdui-panel-item:last-child {
+  border-bottom: none;
+}
+/* 面板头部 */
+.mdui-panel-item-header {
+  position: relative;
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-align: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 100%;
+  height: 48px;
+  padding: 0 24px;
+  font-size: 15px;
+  cursor: pointer;
+  -webkit-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: height, background-color;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-panel-item-header:active {
+  background-color: #EEEEEE;
+}
+/* 面板项标题 */
+.mdui-panel-item-title {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 36%;
+  min-width: 36%;
+  padding-right: 16px;
+  font-weight: 500;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+/* 面板项内容 */
+.mdui-panel-item-summary {
+  -webkit-box-flex: 1;
+      -ms-flex-positive: 1;
+          flex-grow: 1;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding-right: 16px;
+  color: rgba(0, 0, 0, 0.54);
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+/* 展开收起的图标 */
+.mdui-panel-item-arrow {
+  position: absolute;
+  top: 12px;
+  right: 24px;
+  color: rgba(0, 0, 0, 0.54);
+  -webkit-transform: rotate(0);
+          transform: rotate(0);
+  -webkit-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  will-change: transform, top;
+}
+.mdui-panel-item-summary + .mdui-panel-item-arrow {
+  position: relative;
+  top: 0 !important;
+  right: 0;
+}
+/* 面板项内容 */
+.mdui-panel-item-body {
+  height: 0;
+  padding: 0 24px;
+  overflow: hidden;
+  -webkit-transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: height;
+}
+.mdui-panel-item-body::before,
+.mdui-panel-item-body::after {
+  display: table;
+  content: ' ';
+}
+.mdui-panel-item-body::after {
+  clear: both;
+}
+.mdui-panel-item-body::before,
+.mdui-panel-item-body::after {
+  display: table;
+  content: ' ';
+}
+.mdui-panel-item-body::after {
+  clear: both;
+}
+.mdui-panel-item-body::after {
+  height: 16px;
+}
+/* 面板项操作栏 */
+.mdui-panel-item-actions {
+  display: block;
+  width: 100%;
+  margin: 16px -24px 0 -24px;
+  padding: 16px 24px 0 24px;
+  text-align: right;
+  border-top: 1px solid rgba(0, 0, 0, 0.12);
+}
+.mdui-panel-item-actions .mdui-btn {
+  margin-left: 8px;
+}
+.mdui-panel-item-actions .mdui-btn:first-child {
+  margin-left: 0;
+}
+/* 打开状态的面板项 */
+.mdui-panel-item-open {
+  height: auto;
+  margin-top: 16px;
+  margin-bottom: 16px;
+}
+.mdui-panel-item-open > .mdui-panel-item-header {
+  height: 64px;
+}
+.mdui-panel-item-open > .mdui-panel-item-header .mdui-panel-item-arrow {
+  top: 20px;
+  -webkit-transform: rotate(180deg);
+          transform: rotate(180deg);
+}
+.mdui-panel-item-open > .mdui-panel-item-body {
+  height: auto;
+}
+/* 使打开项上下没有边距 */
+.mdui-panel-gapless {
+  -webkit-box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+}
+.mdui-panel-gapless .mdui-panel-item {
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.mdui-panel-gapless .mdui-panel-item-open {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+/* 弹出面板 */
+.mdui-panel-popout .mdui-panel-item-open {
+  margin-right: -16px;
+  margin-left: -16px;
+}
+/**
+ * =============================================================================
+ * ************   Expansion panel dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark {
+  /* stylelint-disable-next-line */
+}
+.mdui-theme-layout-dark .mdui-panel-item {
+  color: #fff;
+  background-color: #303030;
+  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
+}
+.mdui-theme-layout-dark .mdui-panel-item:last-child {
+  border-bottom: none;
+}
+.mdui-theme-layout-dark .mdui-panel-item-header:active {
+  background-color: #424242;
+}
+.mdui-theme-layout-dark .mdui-panel-item-summary {
+  color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-panel-item-arrow {
+  color: #ffffff;
+}
+.mdui-theme-layout-dark .mdui-panel-item-actions {
+  border-top: 1px solid rgba(255, 255, 255, 0.12);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto {
+    /* stylelint-disable-next-line */
+  }
+  .mdui-theme-layout-auto .mdui-panel-item {
+    color: #fff;
+    background-color: #303030;
+    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
+  }
+  .mdui-theme-layout-auto .mdui-panel-item:last-child {
+    border-bottom: none;
+  }
+  .mdui-theme-layout-auto .mdui-panel-item-header:active {
+    background-color: #424242;
+  }
+  .mdui-theme-layout-auto .mdui-panel-item-summary {
+    color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-panel-item-arrow {
+    color: #ffffff;
+  }
+  .mdui-theme-layout-auto .mdui-panel-item-actions {
+    border-top: 1px solid rgba(255, 255, 255, 0.12);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Table 表格   ************
+ * =============================================================================
+ */
+.mdui-table {
+  position: relative;
+  width: 100%;
+  background-color: #fff;
+  border: 1px solid rgba(0, 0, 0, 0.12);
+  border-bottom: none;
+  border-collapse: separate;
+  border-spacing: 0;
+  -webkit-box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+}
+.mdui-table tbody tr {
+  position: relative;
+  -webkit-transition: background-color 0.28s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: background-color 0.28s cubic-bezier(0.4, 0, 0.2, 1);
+}
+.mdui-table th,
+.mdui-table td {
+  position: relative;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 12px 28px;
+  text-align: left;
+  vertical-align: middle;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
+}
+.mdui-table th {
+  color: rgba(0, 0, 0, 0.54);
+  font-weight: 700;
+  font-size: 13px;
+  line-height: 32px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-table td {
+  color: rgba(0, 0, 0, 0.87);
+  font-size: 14px;
+  line-height: 24px;
+}
+/* 每一行前面的复选框 */
+.mdui-table-cell-checkbox {
+  padding-top: 0 !important;
+  padding-bottom: 0 !important;
+  padding-left: 24px !important;
+}
+.mdui-table-cell-checkbox .mdui-checkbox {
+  margin-top: 7px;
+}
+.mdui-table-cell-checkbox + td,
+.mdui-table-cell-checkbox + th {
+  padding-left: 6px !important;
+}
+th.mdui-table-cell-checkbox .mdui-checkbox {
+  margin-top: 11px;
+}
+.mdui-table th:last-child,
+.mdui-table td:last-child {
+  padding-right: 24px;
+}
+.mdui-table th:first-child,
+.mdui-table td:first-child {
+  padding-right: 0;
+  padding-left: 24px;
+}
+.mdui-table th:nth-child(2),
+.mdui-table td:nth-child(2) {
+  padding-left: 24px;
+}
+/* 鼠标悬浮时行背景加深 */
+.mdui-table-hoverable tbody tr:hover {
+  background-color: #EEEEEE;
+}
+/* 表格放到该元素内,使表格产生滚动条时只在该元素内滚动 */
+.mdui-table-fluid {
+  width: 100%;
+  overflow-x: auto;
+  -webkit-overflow-scrolling: touch;
+  border: 1px solid rgba(0, 0, 0, 0.12);
+  border-bottom: none;
+  -webkit-box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+}
+.mdui-table-fluid .mdui-table {
+  -webkit-box-shadow: none;
+          box-shadow: none;
+  margin: 0;
+  border: none;
+}
+/* 数字列,右对齐 */
+.mdui-table-col-numeric {
+  text-align: right !important;
+}
+/* 行处于选中状态 */
+.mdui-table-row-selected {
+  background-color: #F5F5F5;
+}
+/**
+ * =============================================================================
+ * ************   Table dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-table {
+  background-color: #303030;
+  border: 1px solid rgba(255, 255, 255, 0.12);
+  border-bottom: none;
+}
+.mdui-theme-layout-dark .mdui-table th,
+.mdui-theme-layout-dark .mdui-table td {
+  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
+}
+.mdui-theme-layout-dark .mdui-table th {
+  color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-table td {
+  color: #ffffff;
+}
+.mdui-theme-layout-dark .mdui-table-hoverable tbody tr:hover {
+  background-color: #616161;
+}
+.mdui-theme-layout-dark .mdui-table-fluid {
+  border: 1px solid rgba(255, 255, 255, 0.12);
+  border-bottom: none;
+}
+.mdui-theme-layout-dark .mdui-table-fluid .mdui-table {
+  -webkit-box-shadow: none;
+          box-shadow: none;
+  border: none;
+}
+.mdui-theme-layout-dark .mdui-table-row-selected {
+  background-color: #424242;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-table {
+    background-color: #303030;
+    border: 1px solid rgba(255, 255, 255, 0.12);
+    border-bottom: none;
+  }
+  .mdui-theme-layout-auto .mdui-table th,
+  .mdui-theme-layout-auto .mdui-table td {
+    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
+  }
+  .mdui-theme-layout-auto .mdui-table th {
+    color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-table td {
+    color: #ffffff;
+  }
+  .mdui-theme-layout-auto .mdui-table-hoverable tbody tr:hover {
+    background-color: #616161;
+  }
+  .mdui-theme-layout-auto .mdui-table-fluid {
+    border: 1px solid rgba(255, 255, 255, 0.12);
+    border-bottom: none;
+  }
+  .mdui-theme-layout-auto .mdui-table-fluid .mdui-table {
+    -webkit-box-shadow: none;
+            box-shadow: none;
+    border: none;
+  }
+  .mdui-theme-layout-auto .mdui-table-row-selected {
+    background-color: #424242;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Divider 分割线   ************
+ * =============================================================================
+ */
+.mdui-divider,
+.mdui-divider-light,
+.mdui-divider-dark,
+.mdui-divider-inset,
+.mdui-divider-inset-light,
+.mdui-divider-inset-dark {
+  height: 1px;
+  margin: -1px 0 0 0;
+  border: none;
+}
+.mdui-divider-inset,
+.mdui-divider-inset-light,
+.mdui-divider-inset-dark {
+  margin-left: 72px;
+}
+.mdui-divider,
+.mdui-divider-inset {
+  background-color: rgba(0, 0, 0, 0.12);
+}
+.mdui-divider-light,
+.mdui-divider-inset-light {
+  background-color: rgba(255, 255, 255, 0.12);
+}
+.mdui-divider-dark,
+.mdui-divider-inset-dark {
+  background-color: rgba(0, 0, 0, 0.12);
+}
+/**
+ * =============================================================================
+ * ************   Divider dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-divider,
+.mdui-theme-layout-dark .mdui-divider-inset {
+  background-color: rgba(255, 255, 255, 0.12);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-divider,
+  .mdui-theme-layout-auto .mdui-divider-inset {
+    background-color: rgba(255, 255, 255, 0.12);
+  }
+}
+/**
+ * =============================================================================
+ * ************   涟漪动画   ************
+ * =============================================================================
+ */
+.mdui-ripple {
+  position: relative;
+  overflow: hidden;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+}
+/* Ripple */
+.mdui-ripple-wave {
+  position: absolute !important;
+  top: 0;
+  left: 0;
+  z-index: 1;
+  margin: 0;
+  padding: 0;
+  font-size: 0;
+  background-color: rgba(0, 0, 0, 0.1);
+  border-radius: 50%;
+  -webkit-transform: translate3d(0, 0, 0) scale(0);
+          transform: translate3d(0, 0, 0) scale(0);
+  -webkit-transition-duration: 1400ms;
+          transition-duration: 1400ms;
+  pointer-events: none;
+}
+/* 有背景色的默认使用白色涟漪 */
+.mdui-ripple[class*="mdui-color-"] .mdui-ripple-wave {
+  background-color: rgba(255, 255, 255, 0.3);
+}
+/* 白色涟漪 */
+.mdui-ripple-white .mdui-ripple-wave {
+  background-color: rgba(255, 255, 255, 0.3) !important;
+}
+/* 黑色涟漪 */
+.mdui-ripple-black .mdui-ripple-wave {
+  background-color: rgba(0, 0, 0, 0.1) !important;
+}
+.mdui-ripple-wave-fill {
+  opacity: 0.35;
+  -webkit-transition-duration: 300ms;
+          transition-duration: 300ms;
+}
+.mdui-ripple-wave-out {
+  opacity: 0;
+  -webkit-transition-duration: 600ms;
+          transition-duration: 600ms;
+}
+/**
+ * =============================================================================
+ * ************   Ripple 颜色   ************
+ * =============================================================================
+ */
+.mdui-ripple-amber .mdui-ripple-wave {
+  background-color: rgba(255, 193, 7, 0.3) !important;
+}
+.mdui-ripple-blue .mdui-ripple-wave {
+  background-color: rgba(33, 150, 243, 0.3) !important;
+}
+.mdui-ripple-blue-grey .mdui-ripple-wave {
+  background-color: rgba(96, 125, 139, 0.3) !important;
+}
+.mdui-ripple-brown .mdui-ripple-wave {
+  background-color: rgba(121, 85, 72, 0.3) !important;
+}
+.mdui-ripple-cyan .mdui-ripple-wave {
+  background-color: rgba(0, 188, 212, 0.3) !important;
+}
+.mdui-ripple-deep-orange .mdui-ripple-wave {
+  background-color: rgba(255, 87, 34, 0.3) !important;
+}
+.mdui-ripple-deep-purple .mdui-ripple-wave {
+  background-color: rgba(103, 58, 183, 0.3) !important;
+}
+.mdui-ripple-green .mdui-ripple-wave {
+  background-color: rgba(76, 175, 80, 0.3) !important;
+}
+.mdui-ripple-grey .mdui-ripple-wave {
+  background-color: rgba(158, 158, 158, 0.3) !important;
+}
+.mdui-ripple-indigo .mdui-ripple-wave {
+  background-color: rgba(63, 81, 181, 0.3) !important;
+}
+.mdui-ripple-light-blue .mdui-ripple-wave {
+  background-color: rgba(3, 169, 244, 0.3) !important;
+}
+.mdui-ripple-light-green .mdui-ripple-wave {
+  background-color: rgba(139, 195, 74, 0.3) !important;
+}
+.mdui-ripple-lime .mdui-ripple-wave {
+  background-color: rgba(205, 220, 57, 0.3) !important;
+}
+.mdui-ripple-orange .mdui-ripple-wave {
+  background-color: rgba(255, 152, 0, 0.3) !important;
+}
+.mdui-ripple-pink .mdui-ripple-wave {
+  background-color: rgba(233, 30, 99, 0.3) !important;
+}
+.mdui-ripple-purple .mdui-ripple-wave {
+  background-color: rgba(156, 39, 176, 0.3) !important;
+}
+.mdui-ripple-red .mdui-ripple-wave {
+  background-color: rgba(244, 67, 54, 0.3) !important;
+}
+.mdui-ripple-teal .mdui-ripple-wave {
+  background-color: rgba(0, 150, 136, 0.3) !important;
+}
+.mdui-ripple-yellow .mdui-ripple-wave {
+  background-color: rgba(255, 235, 59, 0.3) !important;
+}
+/**
+ * =============================================================================
+ * ************   Ripple dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-ripple-wave {
+  background-color: rgba(255, 255, 255, 0.3);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-ripple-wave {
+    background-color: rgba(255, 255, 255, 0.3);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Text Field 文本框   ************
+ * =============================================================================
+ */
+/* 文本框外层 */
+.mdui-textfield {
+  position: relative;
+  padding-top: 16px;
+  padding-bottom: 8px;
+  overflow: hidden;
+}
+.mdui-textfield-has-bottom {
+  padding-bottom: 28px;
+}
+/* 输入框 */
+.mdui-textfield-input {
+  display: block;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 100%;
+  height: 36px;
+  margin: 0;
+  padding: 8px 0;
+  overflow: hidden;
+  color: rgba(0, 0, 0, 0.87);
+  font-size: 16px;
+  font-family: inherit;
+  line-height: 20px;
+  background: none;
+  border: none;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.42);
+  border-radius: 0;
+  outline: none;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+  -webkit-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+          transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+  -webkit-transition-duration: 0.2s;
+          transition-duration: 0.2s;
+  -webkit-transition-property: border-bottom-color, padding-right, -webkit-box-shadow;
+  transition-property: border-bottom-color, padding-right, -webkit-box-shadow;
+  transition-property: border-bottom-color, padding-right, box-shadow;
+  transition-property: border-bottom-color, padding-right, box-shadow, -webkit-box-shadow;
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+  resize: none;
+}
+.mdui-textfield-input::-webkit-input-placeholder {
+  color: inherit;
+  opacity: 0.42;
+}
+.mdui-textfield-input:not([disabled]):hover {
+  border-bottom: 1px solid rgba(0, 0, 0, 0.87);
+  -webkit-box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.87);
+          box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.87);
+  cursor: pointer;
+}
+.mdui-textfield-input[rows] {
+  height: auto !important;
+  overflow: auto;
+  -webkit-overflow-scrolling: touch;
+}
+/* 文本框 label */
+.mdui-textfield-label {
+  display: block;
+  width: 100%;
+  color: rgba(0, 0, 0, 0.54);
+  font-size: 16px;
+  -webkit-transform: scale(0.75) translateY(0);
+          transform: scale(0.75) translateY(0);
+  -webkit-transform-origin: left;
+          transform-origin: left;
+  -webkit-transition: all 0.2s;
+  transition: all 0.2s;
+  pointer-events: none;
+}
+/* 表单验证错误提示、帮助文本提示 */
+.mdui-textfield-error,
+.mdui-textfield-helper {
+  position: absolute;
+  bottom: 8px;
+  height: 12px;
+  font-size: 12px;
+  line-height: 12px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-textfield-error {
+  color: rgba(255, 23, 68, 0.87);
+  visibility: hidden;
+}
+.mdui-textfield-helper {
+  color: rgba(0, 0, 0, 0.54);
+}
+/* 表单中的图标
+   ========== */
+.mdui-textfield .mdui-icon {
+  position: absolute;
+  bottom: 8px;
+  padding: 6px;
+  color: rgba(0, 0, 0, 0.54);
+}
+.mdui-textfield .mdui-icon ~ .mdui-textfield-label,
+.mdui-textfield .mdui-icon ~ .mdui-textfield-input,
+.mdui-textfield .mdui-icon ~ .mdui-textfield-error,
+.mdui-textfield .mdui-icon ~ .mdui-textfield-helper,
+.mdui-textfield .mdui-icon ~ .mdui-textfield-flex-wrap {
+  /* stylelint-disable-next-line */
+  width: calc(100% - 56px);
+  margin-left: 56px;
+}
+.mdui-textfield-has-bottom .mdui-icon {
+  bottom: 28px;
+}
+/* 聚焦状态的文本框
+   ============= */
+.mdui-textfield-focus .mdui-textfield-input,
+.mdui-textfield-focus .mdui-textfield-input:hover {
+  border-bottom-color: #C51162;
+  -webkit-box-shadow: 0 1px 0 0 #C51162;
+          box-shadow: 0 1px 0 0 #C51162;
+}
+.mdui-textfield-focus .mdui-textfield-label,
+.mdui-textfield-focus .mdui-icon {
+  color: rgba(197, 17, 98, 0.87);
+}
+/* 含有浮动标签的文本框
+   ================ */
+.mdui-textfield-floating-label .mdui-textfield-label {
+  color: rgba(0, 0, 0, 0.35);
+  -webkit-transform: scale(1) translateY(27px);
+          transform: scale(1) translateY(27px);
+}
+.mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-textfield-floating-label.mdui-textfield-not-empty .mdui-textfield-label {
+  color: rgba(0, 0, 0, 0.65);
+  -webkit-transform: scale(0.75) translateY(0);
+          transform: scale(0.75) translateY(0);
+}
+.mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label {
+  color: #E91E63;
+}
+/* 可展开文本框,默认向右展开
+   ========== */
+.mdui-textfield-expandable {
+  width: 36px;
+  min-height: 36px;
+  padding: 1px 0;
+  -webkit-transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+.mdui-textfield-expandable .mdui-icon {
+  bottom: 0;
+  padding: 0;
+}
+.mdui-textfield-expandable .mdui-textfield-input {
+  /* stylelint-disable-next-line */
+  width: calc(100% - 36px);
+  margin-left: 36px;
+  padding-right: 0;
+}
+.mdui-textfield-expandable .mdui-textfield-icon {
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+.mdui-textfield-expandable .mdui-textfield-close {
+  position: absolute;
+  top: 0;
+  right: 0;
+  -webkit-transform: scale(0);
+          transform: scale(0);
+}
+.mdui-textfield-expandable.mdui-textfield-expanded {
+  width: 100%;
+}
+.mdui-textfield-expandable.mdui-textfield-expanded .mdui-textfield-input {
+  padding-right: 36px;
+}
+.mdui-textfield-expandable.mdui-textfield-expanded .mdui-textfield-close {
+  -webkit-transform: scale(1);
+          transform: scale(1);
+}
+/* 表单验证不通过
+   =========== */
+.mdui-textfield-invalid .mdui-textfield-input,
+.mdui-textfield-invalid-html5 .mdui-textfield-input,
+.mdui-textfield-invalid.mdui-textfield-focus .mdui-textfield-input,
+.mdui-textfield-invalid-html5.mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FF1744 !important;
+  -webkit-box-shadow: 0 1px 0 0 #FF1744 !important;
+          box-shadow: 0 1px 0 0 #FF1744 !important;
+}
+.mdui-textfield-invalid .mdui-textfield-label,
+.mdui-textfield-invalid-html5 .mdui-textfield-label {
+  color: #FF1744 !important;
+}
+.mdui-textfield-invalid.mdui-textfield-floating-label .mdui-textfield-label,
+.mdui-textfield-invalid-html5.mdui-textfield-floating-label .mdui-textfield-label {
+  color: rgba(255, 23, 68, 0.35) !important;
+}
+.mdui-textfield-invalid.mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-textfield-invalid-html5.mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-textfield-invalid.mdui-textfield-floating-label.mdui-textfield-not-empty .mdui-textfield-label,
+.mdui-textfield-invalid-html5.mdui-textfield-floating-label.mdui-textfield-not-empty .mdui-textfield-label {
+  color: #FF1744 !important;
+}
+.mdui-textfield-invalid .mdui-textfield-error,
+.mdui-textfield-invalid-html5 .mdui-textfield-error {
+  visibility: visible;
+}
+.mdui-textfield-invalid .mdui-textfield-error + .mdui-textfield-helper,
+.mdui-textfield-invalid-html5 .mdui-textfield-error + .mdui-textfield-helper {
+  visibility: hidden;
+}
+/* 禁用表单
+   ====== */
+.mdui-textfield-disabled .mdui-textfield-label,
+.mdui-textfield-disabled .mdui-textfield-input::-webkit-input-placeholder {
+  color: rgba(0, 0, 0, 0.38);
+}
+.mdui-textfield-disabled .mdui-textfield-input {
+  color: rgba(0, 0, 0, 0.42);
+  cursor: default;
+}
+.mdui-textfield-disabled .mdui-textfield-input {
+  border-bottom: 1px dashed rgba(0, 0, 0, 0.42);
+}
+/* 字数统计
+   ====== */
+.mdui-textfield-counter {
+  position: absolute;
+  right: 8px;
+  bottom: 8px;
+  height: 12px;
+  color: rgba(0, 0, 0, 0.54);
+  font-size: 12px;
+  line-height: 12px;
+}
+/**
+ * =============================================================================
+ * ************   Textfield dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-textfield-input {
+  color: #fff;
+  border-bottom-color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-textfield-input::-webkit-input-placeholder {
+  color: rgba(255, 255, 255, 0.5);
+}
+.mdui-theme-layout-dark .mdui-textfield-input:not([disabled]):hover {
+  border-bottom-color: #ffffff;
+  -webkit-box-shadow: 0 1px 0 0 #ffffff;
+          box-shadow: 0 1px 0 0 #ffffff;
+}
+.mdui-theme-layout-dark .mdui-textfield .mdui-icon {
+  color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-textfield-label {
+  color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-textfield-floating-label .mdui-textfield-label {
+  color: rgba(255, 255, 255, 0.35);
+}
+.mdui-theme-layout-dark .mdui-textfield-error {
+  color: #FF1744;
+}
+.mdui-theme-layout-dark .mdui-textfield-helper {
+  color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-textfield-counter {
+  color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input,
+.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input:hover {
+  border-bottom-color: #FF4081;
+  -webkit-box-shadow: 0 1px 0 0 #FF4081;
+          box-shadow: 0 1px 0 0 #FF4081;
+}
+.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label {
+  color: #FF4081;
+}
+.mdui-theme-layout-dark .mdui-textfield-disabled .mdui-textfield-label,
+.mdui-theme-layout-dark .mdui-textfield-disabled .mdui-textfield-input::-webkit-input-placeholder {
+  color: rgba(255, 255, 255, 0.5);
+}
+.mdui-theme-layout-dark .mdui-textfield-disabled .mdui-textfield-input {
+  color: rgba(255, 255, 255, 0.5);
+}
+.mdui-theme-layout-dark .mdui-textfield-disabled .mdui-textfield-input {
+  border-bottom-color: rgba(255, 255, 255, 0.7);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-textfield-input {
+    color: #fff;
+    border-bottom-color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-textfield-input::-webkit-input-placeholder {
+    color: rgba(255, 255, 255, 0.5);
+  }
+  .mdui-theme-layout-auto .mdui-textfield-input:not([disabled]):hover {
+    border-bottom-color: #ffffff;
+    -webkit-box-shadow: 0 1px 0 0 #ffffff;
+            box-shadow: 0 1px 0 0 #ffffff;
+  }
+  .mdui-theme-layout-auto .mdui-textfield .mdui-icon {
+    color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-textfield-label {
+    color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-textfield-floating-label .mdui-textfield-label {
+    color: rgba(255, 255, 255, 0.35);
+  }
+  .mdui-theme-layout-auto .mdui-textfield-error {
+    color: #FF1744;
+  }
+  .mdui-theme-layout-auto .mdui-textfield-helper {
+    color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-textfield-counter {
+    color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input,
+  .mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input:hover {
+    border-bottom-color: #FF4081;
+    -webkit-box-shadow: 0 1px 0 0 #FF4081;
+            box-shadow: 0 1px 0 0 #FF4081;
+  }
+  .mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label {
+    color: #FF4081;
+  }
+  .mdui-theme-layout-auto .mdui-textfield-disabled .mdui-textfield-label,
+  .mdui-theme-layout-auto .mdui-textfield-disabled .mdui-textfield-input::-webkit-input-placeholder {
+    color: rgba(255, 255, 255, 0.5);
+  }
+  .mdui-theme-layout-auto .mdui-textfield-disabled .mdui-textfield-input {
+    color: rgba(255, 255, 255, 0.5);
+  }
+  .mdui-theme-layout-auto .mdui-textfield-disabled .mdui-textfield-input {
+    border-bottom-color: rgba(255, 255, 255, 0.7);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Textfield 强调色   ************
+ * =============================================================================
+ */
+.mdui-theme-accent-amber .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FFAB00;
+  -webkit-box-shadow: 0 1px 0 0 #FFAB00;
+          box-shadow: 0 1px 0 0 #FFAB00;
+}
+.mdui-theme-accent-amber .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-amber .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-amber .mdui-textfield-focus .mdui-icon {
+  color: rgba(255, 171, 0, 0.87);
+}
+.mdui-theme-accent-amber.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FFD740;
+  -webkit-box-shadow: 0 1px 0 0 #FFD740;
+          box-shadow: 0 1px 0 0 #FFD740;
+}
+.mdui-theme-accent-amber.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-amber.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-amber.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #FFD740;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-amber.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #FFD740;
+    -webkit-box-shadow: 0 1px 0 0 #FFD740;
+            box-shadow: 0 1px 0 0 #FFD740;
+  }
+  .mdui-theme-accent-amber.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-amber.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-amber.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #FFD740;
+  }
+}
+.mdui-theme-accent-blue .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #2962FF;
+  -webkit-box-shadow: 0 1px 0 0 #2962FF;
+          box-shadow: 0 1px 0 0 #2962FF;
+}
+.mdui-theme-accent-blue .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-blue .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-blue .mdui-textfield-focus .mdui-icon {
+  color: rgba(41, 98, 255, 0.87);
+}
+.mdui-theme-accent-blue.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #448AFF;
+  -webkit-box-shadow: 0 1px 0 0 #448AFF;
+          box-shadow: 0 1px 0 0 #448AFF;
+}
+.mdui-theme-accent-blue.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-blue.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-blue.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #448AFF;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-blue.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #448AFF;
+    -webkit-box-shadow: 0 1px 0 0 #448AFF;
+            box-shadow: 0 1px 0 0 #448AFF;
+  }
+  .mdui-theme-accent-blue.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-blue.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-blue.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #448AFF;
+  }
+}
+.mdui-theme-accent-cyan .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #00B8D4;
+  -webkit-box-shadow: 0 1px 0 0 #00B8D4;
+          box-shadow: 0 1px 0 0 #00B8D4;
+}
+.mdui-theme-accent-cyan .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-cyan .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-cyan .mdui-textfield-focus .mdui-icon {
+  color: rgba(0, 184, 212, 0.87);
+}
+.mdui-theme-accent-cyan.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #18FFFF;
+  -webkit-box-shadow: 0 1px 0 0 #18FFFF;
+          box-shadow: 0 1px 0 0 #18FFFF;
+}
+.mdui-theme-accent-cyan.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-cyan.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-cyan.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #18FFFF;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-cyan.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #18FFFF;
+    -webkit-box-shadow: 0 1px 0 0 #18FFFF;
+            box-shadow: 0 1px 0 0 #18FFFF;
+  }
+  .mdui-theme-accent-cyan.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-cyan.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-cyan.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #18FFFF;
+  }
+}
+.mdui-theme-accent-deep-orange .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #DD2C00;
+  -webkit-box-shadow: 0 1px 0 0 #DD2C00;
+          box-shadow: 0 1px 0 0 #DD2C00;
+}
+.mdui-theme-accent-deep-orange .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-deep-orange .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-deep-orange .mdui-textfield-focus .mdui-icon {
+  color: rgba(221, 44, 0, 0.87);
+}
+.mdui-theme-accent-deep-orange.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FF6E40;
+  -webkit-box-shadow: 0 1px 0 0 #FF6E40;
+          box-shadow: 0 1px 0 0 #FF6E40;
+}
+.mdui-theme-accent-deep-orange.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-deep-orange.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-deep-orange.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #FF6E40;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-deep-orange.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #FF6E40;
+    -webkit-box-shadow: 0 1px 0 0 #FF6E40;
+            box-shadow: 0 1px 0 0 #FF6E40;
+  }
+  .mdui-theme-accent-deep-orange.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-deep-orange.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-deep-orange.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #FF6E40;
+  }
+}
+.mdui-theme-accent-deep-purple .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #6200EA;
+  -webkit-box-shadow: 0 1px 0 0 #6200EA;
+          box-shadow: 0 1px 0 0 #6200EA;
+}
+.mdui-theme-accent-deep-purple .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-deep-purple .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-deep-purple .mdui-textfield-focus .mdui-icon {
+  color: rgba(98, 0, 234, 0.87);
+}
+.mdui-theme-accent-deep-purple.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #7C4DFF;
+  -webkit-box-shadow: 0 1px 0 0 #7C4DFF;
+          box-shadow: 0 1px 0 0 #7C4DFF;
+}
+.mdui-theme-accent-deep-purple.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-deep-purple.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-deep-purple.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #7C4DFF;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-deep-purple.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #7C4DFF;
+    -webkit-box-shadow: 0 1px 0 0 #7C4DFF;
+            box-shadow: 0 1px 0 0 #7C4DFF;
+  }
+  .mdui-theme-accent-deep-purple.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-deep-purple.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-deep-purple.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #7C4DFF;
+  }
+}
+.mdui-theme-accent-green .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #00C853;
+  -webkit-box-shadow: 0 1px 0 0 #00C853;
+          box-shadow: 0 1px 0 0 #00C853;
+}
+.mdui-theme-accent-green .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-green .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-green .mdui-textfield-focus .mdui-icon {
+  color: rgba(0, 200, 83, 0.87);
+}
+.mdui-theme-accent-green.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #69F0AE;
+  -webkit-box-shadow: 0 1px 0 0 #69F0AE;
+          box-shadow: 0 1px 0 0 #69F0AE;
+}
+.mdui-theme-accent-green.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-green.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-green.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #69F0AE;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-green.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #69F0AE;
+    -webkit-box-shadow: 0 1px 0 0 #69F0AE;
+            box-shadow: 0 1px 0 0 #69F0AE;
+  }
+  .mdui-theme-accent-green.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-green.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-green.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #69F0AE;
+  }
+}
+.mdui-theme-accent-indigo .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #304FFE;
+  -webkit-box-shadow: 0 1px 0 0 #304FFE;
+          box-shadow: 0 1px 0 0 #304FFE;
+}
+.mdui-theme-accent-indigo .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-indigo .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-indigo .mdui-textfield-focus .mdui-icon {
+  color: rgba(48, 79, 254, 0.87);
+}
+.mdui-theme-accent-indigo.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #536DFE;
+  -webkit-box-shadow: 0 1px 0 0 #536DFE;
+          box-shadow: 0 1px 0 0 #536DFE;
+}
+.mdui-theme-accent-indigo.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-indigo.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-indigo.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #536DFE;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-indigo.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #536DFE;
+    -webkit-box-shadow: 0 1px 0 0 #536DFE;
+            box-shadow: 0 1px 0 0 #536DFE;
+  }
+  .mdui-theme-accent-indigo.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-indigo.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-indigo.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #536DFE;
+  }
+}
+.mdui-theme-accent-light-blue .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #0091EA;
+  -webkit-box-shadow: 0 1px 0 0 #0091EA;
+          box-shadow: 0 1px 0 0 #0091EA;
+}
+.mdui-theme-accent-light-blue .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-light-blue .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-light-blue .mdui-textfield-focus .mdui-icon {
+  color: rgba(0, 145, 234, 0.87);
+}
+.mdui-theme-accent-light-blue.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #40C4FF;
+  -webkit-box-shadow: 0 1px 0 0 #40C4FF;
+          box-shadow: 0 1px 0 0 #40C4FF;
+}
+.mdui-theme-accent-light-blue.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-light-blue.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-light-blue.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #40C4FF;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-light-blue.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #40C4FF;
+    -webkit-box-shadow: 0 1px 0 0 #40C4FF;
+            box-shadow: 0 1px 0 0 #40C4FF;
+  }
+  .mdui-theme-accent-light-blue.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-light-blue.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-light-blue.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #40C4FF;
+  }
+}
+.mdui-theme-accent-light-green .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #64DD17;
+  -webkit-box-shadow: 0 1px 0 0 #64DD17;
+          box-shadow: 0 1px 0 0 #64DD17;
+}
+.mdui-theme-accent-light-green .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-light-green .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-light-green .mdui-textfield-focus .mdui-icon {
+  color: rgba(100, 221, 23, 0.87);
+}
+.mdui-theme-accent-light-green.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #B2FF59;
+  -webkit-box-shadow: 0 1px 0 0 #B2FF59;
+          box-shadow: 0 1px 0 0 #B2FF59;
+}
+.mdui-theme-accent-light-green.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-light-green.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-light-green.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #B2FF59;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-light-green.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #B2FF59;
+    -webkit-box-shadow: 0 1px 0 0 #B2FF59;
+            box-shadow: 0 1px 0 0 #B2FF59;
+  }
+  .mdui-theme-accent-light-green.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-light-green.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-light-green.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #B2FF59;
+  }
+}
+.mdui-theme-accent-lime .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #AEEA00;
+  -webkit-box-shadow: 0 1px 0 0 #AEEA00;
+          box-shadow: 0 1px 0 0 #AEEA00;
+}
+.mdui-theme-accent-lime .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-lime .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-lime .mdui-textfield-focus .mdui-icon {
+  color: rgba(174, 234, 0, 0.87);
+}
+.mdui-theme-accent-lime.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #EEFF41;
+  -webkit-box-shadow: 0 1px 0 0 #EEFF41;
+          box-shadow: 0 1px 0 0 #EEFF41;
+}
+.mdui-theme-accent-lime.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-lime.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-lime.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #EEFF41;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-lime.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #EEFF41;
+    -webkit-box-shadow: 0 1px 0 0 #EEFF41;
+            box-shadow: 0 1px 0 0 #EEFF41;
+  }
+  .mdui-theme-accent-lime.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-lime.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-lime.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #EEFF41;
+  }
+}
+.mdui-theme-accent-orange .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FF6D00;
+  -webkit-box-shadow: 0 1px 0 0 #FF6D00;
+          box-shadow: 0 1px 0 0 #FF6D00;
+}
+.mdui-theme-accent-orange .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-orange .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-orange .mdui-textfield-focus .mdui-icon {
+  color: rgba(255, 109, 0, 0.87);
+}
+.mdui-theme-accent-orange.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FFAB40;
+  -webkit-box-shadow: 0 1px 0 0 #FFAB40;
+          box-shadow: 0 1px 0 0 #FFAB40;
+}
+.mdui-theme-accent-orange.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-orange.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-orange.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #FFAB40;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-orange.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #FFAB40;
+    -webkit-box-shadow: 0 1px 0 0 #FFAB40;
+            box-shadow: 0 1px 0 0 #FFAB40;
+  }
+  .mdui-theme-accent-orange.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-orange.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-orange.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #FFAB40;
+  }
+}
+.mdui-theme-accent-pink .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #C51162;
+  -webkit-box-shadow: 0 1px 0 0 #C51162;
+          box-shadow: 0 1px 0 0 #C51162;
+}
+.mdui-theme-accent-pink .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-pink .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-pink .mdui-textfield-focus .mdui-icon {
+  color: rgba(197, 17, 98, 0.87);
+}
+.mdui-theme-accent-pink.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FF4081;
+  -webkit-box-shadow: 0 1px 0 0 #FF4081;
+          box-shadow: 0 1px 0 0 #FF4081;
+}
+.mdui-theme-accent-pink.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-pink.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-pink.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #FF4081;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-pink.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #FF4081;
+    -webkit-box-shadow: 0 1px 0 0 #FF4081;
+            box-shadow: 0 1px 0 0 #FF4081;
+  }
+  .mdui-theme-accent-pink.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-pink.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-pink.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #FF4081;
+  }
+}
+.mdui-theme-accent-purple .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #AA00FF;
+  -webkit-box-shadow: 0 1px 0 0 #AA00FF;
+          box-shadow: 0 1px 0 0 #AA00FF;
+}
+.mdui-theme-accent-purple .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-purple .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-purple .mdui-textfield-focus .mdui-icon {
+  color: rgba(170, 0, 255, 0.87);
+}
+.mdui-theme-accent-purple.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #E040FB;
+  -webkit-box-shadow: 0 1px 0 0 #E040FB;
+          box-shadow: 0 1px 0 0 #E040FB;
+}
+.mdui-theme-accent-purple.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-purple.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-purple.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #E040FB;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-purple.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #E040FB;
+    -webkit-box-shadow: 0 1px 0 0 #E040FB;
+            box-shadow: 0 1px 0 0 #E040FB;
+  }
+  .mdui-theme-accent-purple.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-purple.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-purple.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #E040FB;
+  }
+}
+.mdui-theme-accent-red .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #D50000;
+  -webkit-box-shadow: 0 1px 0 0 #D50000;
+          box-shadow: 0 1px 0 0 #D50000;
+}
+.mdui-theme-accent-red .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-red .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-red .mdui-textfield-focus .mdui-icon {
+  color: rgba(213, 0, 0, 0.87);
+}
+.mdui-theme-accent-red.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FF5252;
+  -webkit-box-shadow: 0 1px 0 0 #FF5252;
+          box-shadow: 0 1px 0 0 #FF5252;
+}
+.mdui-theme-accent-red.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-red.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-red.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #FF5252;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-red.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #FF5252;
+    -webkit-box-shadow: 0 1px 0 0 #FF5252;
+            box-shadow: 0 1px 0 0 #FF5252;
+  }
+  .mdui-theme-accent-red.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-red.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-red.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #FF5252;
+  }
+}
+.mdui-theme-accent-teal .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #00BFA5;
+  -webkit-box-shadow: 0 1px 0 0 #00BFA5;
+          box-shadow: 0 1px 0 0 #00BFA5;
+}
+.mdui-theme-accent-teal .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-teal .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-teal .mdui-textfield-focus .mdui-icon {
+  color: rgba(0, 191, 165, 0.87);
+}
+.mdui-theme-accent-teal.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #64FFDA;
+  -webkit-box-shadow: 0 1px 0 0 #64FFDA;
+          box-shadow: 0 1px 0 0 #64FFDA;
+}
+.mdui-theme-accent-teal.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-teal.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-teal.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #64FFDA;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-teal.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #64FFDA;
+    -webkit-box-shadow: 0 1px 0 0 #64FFDA;
+            box-shadow: 0 1px 0 0 #64FFDA;
+  }
+  .mdui-theme-accent-teal.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-teal.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-teal.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #64FFDA;
+  }
+}
+.mdui-theme-accent-yellow .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FFD600;
+  -webkit-box-shadow: 0 1px 0 0 #FFD600;
+          box-shadow: 0 1px 0 0 #FFD600;
+}
+.mdui-theme-accent-yellow .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-yellow .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-yellow .mdui-textfield-focus .mdui-icon {
+  color: rgba(255, 214, 0, 0.87);
+}
+.mdui-theme-accent-yellow.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-input {
+  border-bottom-color: #FFFF00;
+  -webkit-box-shadow: 0 1px 0 0 #FFFF00;
+          box-shadow: 0 1px 0 0 #FFFF00;
+}
+.mdui-theme-accent-yellow.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-yellow.mdui-theme-layout-dark .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+.mdui-theme-accent-yellow.mdui-theme-layout-dark .mdui-textfield-focus .mdui-icon {
+  color: #FFFF00;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-accent-yellow.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-input {
+    border-bottom-color: #FFFF00;
+    -webkit-box-shadow: 0 1px 0 0 #FFFF00;
+            box-shadow: 0 1px 0 0 #FFFF00;
+  }
+  .mdui-theme-accent-yellow.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-yellow.mdui-theme-layout-auto .mdui-textfield-focus .mdui-textfield-floating-label.mdui-textfield-focus .mdui-textfield-label,
+  .mdui-theme-accent-yellow.mdui-theme-layout-auto .mdui-textfield-focus .mdui-icon {
+    color: #FFFF00;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Checkbox 复选框   ************
+ * =============================================================================
+ */
+.mdui-checkbox {
+  position: relative;
+  display: inline-block;
+  height: 36px;
+  padding-left: 36px;
+  line-height: 36px;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+}
+.mdui-checkbox input[type="checkbox"] {
+  position: absolute;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+  opacity: 0;
+}
+/* 透明的圆形,用于生成圆形阴影 */
+.mdui-checkbox-icon {
+  position: absolute;
+  top: 9px;
+  left: 0;
+  display: inline-block;
+  width: 18px;
+  height: 18px;
+  vertical-align: middle;
+  background-color: transparent;
+  border: none;
+  border-radius: 18px;
+  -webkit-transition: -webkit-box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: -webkit-box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+}
+.mdui-checkbox-icon::after {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 0;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 18px;
+  height: 18px;
+  border: 2px solid rgba(0, 0, 0, 0.54);
+  border-radius: 2px;
+  -webkit-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  content: ' ';
+}
+.mdui-checkbox-icon::before {
+  position: absolute;
+  top: 2px;
+  left: 0;
+  z-index: 1;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 8px;
+  height: 13px;
+  border-right: 2px solid #fff;
+  border-bottom: 2px solid #fff;
+  -webkit-transform: rotateZ(37deg) scale(0);
+          transform: rotateZ(37deg) scale(0);
+  -webkit-transform-origin: 100% 100%;
+          transform-origin: 100% 100%;
+  opacity: 0;
+  -webkit-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  content: ' ';
+}
+/* 各种状态的图标 */
+.mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after {
+  background-color: #FF4081;
+  border-color: #FF4081;
+}
+.mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::before {
+  -webkit-transform: rotateZ(37deg) scale(1);
+          transform: rotateZ(37deg) scale(1);
+  opacity: 1;
+}
+.mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #FF4081;
+  border-color: #FF4081;
+}
+.mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::before {
+  top: 8px;
+  left: 3px;
+  width: 12px;
+  height: 0;
+  border-right: none;
+  border-bottom: 2px solid #fff;
+  border-radius: 1px;
+  -webkit-transform: rotateZ(0) scale(1);
+          transform: rotateZ(0) scale(1);
+  opacity: 1;
+}
+.mdui-checkbox input[type="checkbox"]:disabled + .mdui-checkbox-icon::after {
+  border-color: rgba(0, 0, 0, 0.26);
+}
+.mdui-checkbox input[type="checkbox"]:disabled:checked + .mdui-checkbox-icon::after,
+.mdui-checkbox input[type="checkbox"]:disabled:indeterminate + .mdui-checkbox-icon::after {
+  background-color: rgba(0, 0, 0, 0.26) !important;
+  border-color: transparent !important;
+}
+/* 阴影 */
+.mdui-checkbox:active input[type="checkbox"] + .mdui-checkbox-icon,
+.mdui-checkbox input[type="checkbox"]:focus + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 0 0 15px rgba(0, 0, 0, 0.1);
+}
+.mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 64, 129, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 64, 129, 0.16);
+}
+/**
+ * =============================================================================
+ * ************   Checkbox 强调色   ************
+ * =============================================================================
+ */
+.mdui-theme-accent-amber .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-amber .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #FFD740;
+  border-color: #FFD740;
+}
+.mdui-theme-accent-amber .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-amber .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-amber .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-amber .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 215, 64, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 215, 64, 0.16);
+}
+.mdui-theme-accent-blue .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-blue .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #448AFF;
+  border-color: #448AFF;
+}
+.mdui-theme-accent-blue .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-blue .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-blue .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-blue .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(68, 138, 255, 0.16);
+          box-shadow: 0 0 0 15px rgba(68, 138, 255, 0.16);
+}
+.mdui-theme-accent-cyan .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-cyan .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #18FFFF;
+  border-color: #18FFFF;
+}
+.mdui-theme-accent-cyan .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-cyan .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-cyan .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-cyan .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(24, 255, 255, 0.16);
+          box-shadow: 0 0 0 15px rgba(24, 255, 255, 0.16);
+}
+.mdui-theme-accent-deep-orange .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-deep-orange .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #FF6E40;
+  border-color: #FF6E40;
+}
+.mdui-theme-accent-deep-orange .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-deep-orange .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-deep-orange .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-deep-orange .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 110, 64, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 110, 64, 0.16);
+}
+.mdui-theme-accent-deep-purple .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-deep-purple .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #7C4DFF;
+  border-color: #7C4DFF;
+}
+.mdui-theme-accent-deep-purple .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-deep-purple .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-deep-purple .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-deep-purple .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(124, 77, 255, 0.16);
+          box-shadow: 0 0 0 15px rgba(124, 77, 255, 0.16);
+}
+.mdui-theme-accent-green .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-green .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #69F0AE;
+  border-color: #69F0AE;
+}
+.mdui-theme-accent-green .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-green .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-green .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-green .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(105, 240, 174, 0.16);
+          box-shadow: 0 0 0 15px rgba(105, 240, 174, 0.16);
+}
+.mdui-theme-accent-indigo .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-indigo .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #536DFE;
+  border-color: #536DFE;
+}
+.mdui-theme-accent-indigo .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-indigo .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-indigo .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-indigo .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(83, 109, 254, 0.16);
+          box-shadow: 0 0 0 15px rgba(83, 109, 254, 0.16);
+}
+.mdui-theme-accent-light-blue .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-light-blue .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #40C4FF;
+  border-color: #40C4FF;
+}
+.mdui-theme-accent-light-blue .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-light-blue .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-light-blue .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-light-blue .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(64, 196, 255, 0.16);
+          box-shadow: 0 0 0 15px rgba(64, 196, 255, 0.16);
+}
+.mdui-theme-accent-light-green .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-light-green .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #B2FF59;
+  border-color: #B2FF59;
+}
+.mdui-theme-accent-light-green .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-light-green .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-light-green .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-light-green .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(178, 255, 89, 0.16);
+          box-shadow: 0 0 0 15px rgba(178, 255, 89, 0.16);
+}
+.mdui-theme-accent-lime .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-lime .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #EEFF41;
+  border-color: #EEFF41;
+}
+.mdui-theme-accent-lime .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-lime .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-lime .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-lime .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(238, 255, 65, 0.16);
+          box-shadow: 0 0 0 15px rgba(238, 255, 65, 0.16);
+}
+.mdui-theme-accent-orange .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-orange .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #FFAB40;
+  border-color: #FFAB40;
+}
+.mdui-theme-accent-orange .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-orange .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-orange .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-orange .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 171, 64, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 171, 64, 0.16);
+}
+.mdui-theme-accent-pink .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-pink .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #FF4081;
+  border-color: #FF4081;
+}
+.mdui-theme-accent-pink .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-pink .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-pink .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-pink .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 64, 129, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 64, 129, 0.16);
+}
+.mdui-theme-accent-purple .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-purple .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #E040FB;
+  border-color: #E040FB;
+}
+.mdui-theme-accent-purple .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-purple .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-purple .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-purple .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(224, 64, 251, 0.16);
+          box-shadow: 0 0 0 15px rgba(224, 64, 251, 0.16);
+}
+.mdui-theme-accent-red .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-red .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #FF5252;
+  border-color: #FF5252;
+}
+.mdui-theme-accent-red .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-red .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-red .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-red .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 82, 82, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 82, 82, 0.16);
+}
+.mdui-theme-accent-teal .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-teal .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #64FFDA;
+  border-color: #64FFDA;
+}
+.mdui-theme-accent-teal .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-teal .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-teal .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-teal .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(100, 255, 218, 0.16);
+          box-shadow: 0 0 0 15px rgba(100, 255, 218, 0.16);
+}
+.mdui-theme-accent-yellow .mdui-checkbox input[type="checkbox"]:checked + .mdui-checkbox-icon::after,
+.mdui-theme-accent-yellow .mdui-checkbox input[type="checkbox"]:indeterminate + .mdui-checkbox-icon::after {
+  background-color: #FFFF00;
+  border-color: #FFFF00;
+}
+.mdui-theme-accent-yellow .mdui-checkbox:active input[type="checkbox"]:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-yellow .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):checked + .mdui-checkbox-icon,
+.mdui-theme-accent-yellow .mdui-checkbox:active input[type="checkbox"]:not(:disabled):indeterminate + .mdui-checkbox-icon,
+.mdui-theme-accent-yellow .mdui-checkbox input[type="checkbox"]:focus:not(:disabled):indeterminate + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 255, 0, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 255, 0, 0.16);
+}
+/**
+ * =============================================================================
+ * ************   Checkbox dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-checkbox-icon::after {
+  border-color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-checkbox-icon::before {
+  border-right-color: #303030 !important;
+  border-bottom-color: #303030 !important;
+}
+.mdui-theme-layout-dark .mdui-checkbox input[type="checkbox"]:disabled + .mdui-checkbox-icon::after {
+  border-color: rgba(255, 255, 255, 0.3);
+}
+.mdui-theme-layout-dark .mdui-checkbox input[type="checkbox"]:disabled:checked + .mdui-checkbox-icon::after,
+.mdui-theme-layout-dark .mdui-checkbox input[type="checkbox"]:disabled:indeterminate + .mdui-checkbox-icon::after {
+  background-color: rgba(255, 255, 255, 0.3) !important;
+  border-color: transparent !important;
+}
+.mdui-theme-layout-dark .mdui-checkbox:active input[type="checkbox"] + .mdui-checkbox-icon,
+.mdui-theme-layout-dark .mdui-checkbox input[type="checkbox"]:focus + .mdui-checkbox-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 255, 255, 0.1);
+          box-shadow: 0 0 0 15px rgba(255, 255, 255, 0.1);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-checkbox-icon::after {
+    border-color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-checkbox-icon::before {
+    border-right-color: #303030 !important;
+    border-bottom-color: #303030 !important;
+  }
+  .mdui-theme-layout-auto .mdui-checkbox input[type="checkbox"]:disabled + .mdui-checkbox-icon::after {
+    border-color: rgba(255, 255, 255, 0.3);
+  }
+  .mdui-theme-layout-auto .mdui-checkbox input[type="checkbox"]:disabled:checked + .mdui-checkbox-icon::after,
+  .mdui-theme-layout-auto .mdui-checkbox input[type="checkbox"]:disabled:indeterminate + .mdui-checkbox-icon::after {
+    background-color: rgba(255, 255, 255, 0.3) !important;
+    border-color: transparent !important;
+  }
+  .mdui-theme-layout-auto .mdui-checkbox:active input[type="checkbox"] + .mdui-checkbox-icon,
+  .mdui-theme-layout-auto .mdui-checkbox input[type="checkbox"]:focus + .mdui-checkbox-icon {
+    -webkit-box-shadow: 0 0 0 15px rgba(255, 255, 255, 0.1);
+            box-shadow: 0 0 0 15px rgba(255, 255, 255, 0.1);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Radio 单选框   ************
+ * =============================================================================
+ */
+.mdui-radio {
+  position: relative;
+  display: inline-block;
+  height: 36px;
+  padding-left: 36px;
+  line-height: 36px;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+}
+.mdui-radio input {
+  position: absolute;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+  opacity: 0;
+}
+/* 图标外圈 */
+.mdui-radio-icon {
+  position: absolute;
+  top: 9px;
+  left: 0;
+  display: inline-block;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 18px;
+  height: 18px;
+  vertical-align: middle;
+  border: 2px solid rgba(0, 0, 0, 0.54);
+  border-radius: 18px;
+  -webkit-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+}
+.mdui-radio-icon::before {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 14px;
+  height: 14px;
+  background-color: #FF4081;
+  border-radius: 14px;
+  -webkit-transform: scale(0);
+          transform: scale(0);
+  opacity: 0;
+  -webkit-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  content: ' ';
+}
+/* 选中状态的图标 */
+.mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #FF4081;
+}
+.mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  -webkit-transform: scale(0.68);
+          transform: scale(0.68);
+  opacity: 1;
+}
+/* 禁用状态的图标 */
+.mdui-radio input[type="radio"]:disabled + .mdui-radio-icon {
+  border-color: rgba(0, 0, 0, 0.26) !important;
+}
+/* 禁用且选中状态的图标 */
+.mdui-radio input[type="radio"]:disabled:checked + .mdui-radio-icon::before {
+  background-color: rgba(0, 0, 0, 0.26) !important;
+}
+/* 未选中、禁用时 按下的阴影 */
+.mdui-radio:active input[type="radio"] + .mdui-radio-icon,
+.mdui-radio input[type="radio"]:focus + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 0 0 15px rgba(0, 0, 0, 0.1);
+}
+/* 已选中时按下的阴影 */
+.mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 64, 129, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 64, 129, 0.16);
+}
+/**
+ * =============================================================================
+ * ************   Radio 强调色   ************
+ * =============================================================================
+ */
+.mdui-theme-accent-amber .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #FFD740;
+}
+.mdui-theme-accent-amber .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #FFD740;
+}
+.mdui-theme-accent-amber .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-amber .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 215, 64, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 215, 64, 0.16);
+}
+.mdui-theme-accent-blue .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #448AFF;
+}
+.mdui-theme-accent-blue .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #448AFF;
+}
+.mdui-theme-accent-blue .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-blue .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(68, 138, 255, 0.16);
+          box-shadow: 0 0 0 15px rgba(68, 138, 255, 0.16);
+}
+.mdui-theme-accent-cyan .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #18FFFF;
+}
+.mdui-theme-accent-cyan .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #18FFFF;
+}
+.mdui-theme-accent-cyan .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-cyan .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(24, 255, 255, 0.16);
+          box-shadow: 0 0 0 15px rgba(24, 255, 255, 0.16);
+}
+.mdui-theme-accent-deep-orange .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #FF6E40;
+}
+.mdui-theme-accent-deep-orange .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #FF6E40;
+}
+.mdui-theme-accent-deep-orange .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-deep-orange .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 110, 64, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 110, 64, 0.16);
+}
+.mdui-theme-accent-deep-purple .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #7C4DFF;
+}
+.mdui-theme-accent-deep-purple .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #7C4DFF;
+}
+.mdui-theme-accent-deep-purple .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-deep-purple .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(124, 77, 255, 0.16);
+          box-shadow: 0 0 0 15px rgba(124, 77, 255, 0.16);
+}
+.mdui-theme-accent-green .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #69F0AE;
+}
+.mdui-theme-accent-green .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #69F0AE;
+}
+.mdui-theme-accent-green .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-green .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(105, 240, 174, 0.16);
+          box-shadow: 0 0 0 15px rgba(105, 240, 174, 0.16);
+}
+.mdui-theme-accent-indigo .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #536DFE;
+}
+.mdui-theme-accent-indigo .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #536DFE;
+}
+.mdui-theme-accent-indigo .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-indigo .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(83, 109, 254, 0.16);
+          box-shadow: 0 0 0 15px rgba(83, 109, 254, 0.16);
+}
+.mdui-theme-accent-light-blue .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #40C4FF;
+}
+.mdui-theme-accent-light-blue .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #40C4FF;
+}
+.mdui-theme-accent-light-blue .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-light-blue .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(64, 196, 255, 0.16);
+          box-shadow: 0 0 0 15px rgba(64, 196, 255, 0.16);
+}
+.mdui-theme-accent-light-green .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #B2FF59;
+}
+.mdui-theme-accent-light-green .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #B2FF59;
+}
+.mdui-theme-accent-light-green .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-light-green .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(178, 255, 89, 0.16);
+          box-shadow: 0 0 0 15px rgba(178, 255, 89, 0.16);
+}
+.mdui-theme-accent-lime .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #EEFF41;
+}
+.mdui-theme-accent-lime .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #EEFF41;
+}
+.mdui-theme-accent-lime .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-lime .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(238, 255, 65, 0.16);
+          box-shadow: 0 0 0 15px rgba(238, 255, 65, 0.16);
+}
+.mdui-theme-accent-orange .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #FFAB40;
+}
+.mdui-theme-accent-orange .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #FFAB40;
+}
+.mdui-theme-accent-orange .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-orange .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 171, 64, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 171, 64, 0.16);
+}
+.mdui-theme-accent-pink .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #FF4081;
+}
+.mdui-theme-accent-pink .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #FF4081;
+}
+.mdui-theme-accent-pink .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-pink .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 64, 129, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 64, 129, 0.16);
+}
+.mdui-theme-accent-purple .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #E040FB;
+}
+.mdui-theme-accent-purple .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #E040FB;
+}
+.mdui-theme-accent-purple .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-purple .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(224, 64, 251, 0.16);
+          box-shadow: 0 0 0 15px rgba(224, 64, 251, 0.16);
+}
+.mdui-theme-accent-red .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #FF5252;
+}
+.mdui-theme-accent-red .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #FF5252;
+}
+.mdui-theme-accent-red .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-red .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 82, 82, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 82, 82, 0.16);
+}
+.mdui-theme-accent-teal .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #64FFDA;
+}
+.mdui-theme-accent-teal .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #64FFDA;
+}
+.mdui-theme-accent-teal .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-teal .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(100, 255, 218, 0.16);
+          box-shadow: 0 0 0 15px rgba(100, 255, 218, 0.16);
+}
+.mdui-theme-accent-yellow .mdui-radio input[type="radio"]:checked + .mdui-radio-icon {
+  border-color: #FFFF00;
+}
+.mdui-theme-accent-yellow .mdui-radio input[type="radio"]:checked + .mdui-radio-icon::before {
+  background-color: #FFFF00;
+}
+.mdui-theme-accent-yellow .mdui-radio:active input[type="radio"]:checked:not(:disabled) + .mdui-radio-icon,
+.mdui-theme-accent-yellow .mdui-radio input[type="radio"]:focus:checked:not(:disabled) + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 255, 0, 0.16);
+          box-shadow: 0 0 0 15px rgba(255, 255, 0, 0.16);
+}
+/**
+ * =============================================================================
+ * ************   Radio dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-radio-icon {
+  border-color: rgba(255, 255, 255, 0.7);
+}
+.mdui-theme-layout-dark .mdui-radio input[type="radio"]:disabled + .mdui-radio-icon {
+  border-color: rgba(255, 255, 255, 0.3) !important;
+}
+.mdui-theme-layout-dark .mdui-radio input[type="radio"]:disabled:checked + .mdui-radio-icon::before {
+  background-color: rgba(255, 255, 255, 0.3) !important;
+}
+.mdui-theme-layout-dark .mdui-radio:active input[type="radio"] + .mdui-radio-icon,
+.mdui-theme-layout-dark .mdui-radio input[type="radio"]:focus + .mdui-radio-icon {
+  -webkit-box-shadow: 0 0 0 15px rgba(255, 255, 255, 0.1);
+          box-shadow: 0 0 0 15px rgba(255, 255, 255, 0.1);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-radio-icon {
+    border-color: rgba(255, 255, 255, 0.7);
+  }
+  .mdui-theme-layout-auto .mdui-radio input[type="radio"]:disabled + .mdui-radio-icon {
+    border-color: rgba(255, 255, 255, 0.3) !important;
+  }
+  .mdui-theme-layout-auto .mdui-radio input[type="radio"]:disabled:checked + .mdui-radio-icon::before {
+    background-color: rgba(255, 255, 255, 0.3) !important;
+  }
+  .mdui-theme-layout-auto .mdui-radio:active input[type="radio"] + .mdui-radio-icon,
+  .mdui-theme-layout-auto .mdui-radio input[type="radio"]:focus + .mdui-radio-icon {
+    -webkit-box-shadow: 0 0 0 15px rgba(255, 255, 255, 0.1);
+            box-shadow: 0 0 0 15px rgba(255, 255, 255, 0.1);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Switch 单选框   ************
+ * =============================================================================
+ */
+.mdui-switch {
+  display: inline-block;
+  height: 36px;
+  line-height: 36px;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+}
+.mdui-switch input {
+  position: absolute;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+  opacity: 0;
+}
+/* 图标轨道 */
+.mdui-switch-icon {
+  position: relative;
+  display: inline-block;
+  width: 36px;
+  height: 14px;
+  vertical-align: middle;
+  background-color: rgba(0, 0, 0, 0.38);
+  border-radius: 14px;
+  -webkit-transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+.mdui-switch-icon::before {
+  position: absolute;
+  top: -3px;
+  left: -3px;
+  display: inline-block;
+  width: 20px;
+  height: 20px;
+  background-color: #FAFAFA;
+  border-radius: 20px;
+  -webkit-transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), left 0.3s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), left 0.3s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), left 0.3s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.14s cubic-bezier(0.4, 0, 0.2, 1);
+  content: ' ';
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12);
+}
+/* 选中状态的图标 */
+.mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 64, 129, 0.5);
+}
+.mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  left: 20px;
+  background-color: #FF4081;
+}
+/* 未选中时或禁用时 按下的阴影 */
+.mdui-switch:active input[type="checkbox"] + .mdui-switch-icon::before,
+.mdui-switch input[type="checkbox"]:focus + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(0, 0, 0, 0.1);
+}
+/* 已选中时按下的阴影 */
+.mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 64, 129, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 64, 129, 0.16);
+}
+/* 禁用状态 */
+.mdui-switch input[type="checkbox"]:disabled + .mdui-switch-icon {
+  background-color: rgba(0, 0, 0, 0.12) !important;
+}
+.mdui-switch input[type="checkbox"]:disabled + .mdui-switch-icon::before {
+  background-color: #BDBDBD !important;
+}
+/**
+ * =============================================================================
+ * ************   Switch 强调色   ************
+ * =============================================================================
+ */
+.mdui-theme-accent-amber .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 215, 64, 0.5);
+}
+.mdui-theme-accent-amber .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FFD740;
+}
+.mdui-theme-accent-amber .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-amber .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 215, 64, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 215, 64, 0.16);
+}
+.mdui-theme-accent-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(68, 138, 255, 0.5);
+}
+.mdui-theme-accent-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #448AFF;
+}
+.mdui-theme-accent-blue .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-blue .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(68, 138, 255, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(68, 138, 255, 0.16);
+}
+.mdui-theme-accent-cyan .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(24, 255, 255, 0.5);
+}
+.mdui-theme-accent-cyan .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #18FFFF;
+}
+.mdui-theme-accent-cyan .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-cyan .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(24, 255, 255, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(24, 255, 255, 0.16);
+}
+.mdui-theme-accent-deep-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 110, 64, 0.5);
+}
+.mdui-theme-accent-deep-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FF6E40;
+}
+.mdui-theme-accent-deep-orange .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-deep-orange .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 110, 64, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 110, 64, 0.16);
+}
+.mdui-theme-accent-deep-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(124, 77, 255, 0.5);
+}
+.mdui-theme-accent-deep-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #7C4DFF;
+}
+.mdui-theme-accent-deep-purple .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-deep-purple .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(124, 77, 255, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(124, 77, 255, 0.16);
+}
+.mdui-theme-accent-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(105, 240, 174, 0.5);
+}
+.mdui-theme-accent-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #69F0AE;
+}
+.mdui-theme-accent-green .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-green .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(105, 240, 174, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(105, 240, 174, 0.16);
+}
+.mdui-theme-accent-indigo .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(83, 109, 254, 0.5);
+}
+.mdui-theme-accent-indigo .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #536DFE;
+}
+.mdui-theme-accent-indigo .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-indigo .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(83, 109, 254, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(83, 109, 254, 0.16);
+}
+.mdui-theme-accent-light-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(64, 196, 255, 0.5);
+}
+.mdui-theme-accent-light-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #40C4FF;
+}
+.mdui-theme-accent-light-blue .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-light-blue .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(64, 196, 255, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(64, 196, 255, 0.16);
+}
+.mdui-theme-accent-light-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(178, 255, 89, 0.5);
+}
+.mdui-theme-accent-light-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #B2FF59;
+}
+.mdui-theme-accent-light-green .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-light-green .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(178, 255, 89, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(178, 255, 89, 0.16);
+}
+.mdui-theme-accent-lime .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(238, 255, 65, 0.5);
+}
+.mdui-theme-accent-lime .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #EEFF41;
+}
+.mdui-theme-accent-lime .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-lime .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(238, 255, 65, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(238, 255, 65, 0.16);
+}
+.mdui-theme-accent-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 171, 64, 0.5);
+}
+.mdui-theme-accent-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FFAB40;
+}
+.mdui-theme-accent-orange .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-orange .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 171, 64, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 171, 64, 0.16);
+}
+.mdui-theme-accent-pink .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 64, 129, 0.5);
+}
+.mdui-theme-accent-pink .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FF4081;
+}
+.mdui-theme-accent-pink .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-pink .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 64, 129, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 64, 129, 0.16);
+}
+.mdui-theme-accent-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(224, 64, 251, 0.5);
+}
+.mdui-theme-accent-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #E040FB;
+}
+.mdui-theme-accent-purple .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-purple .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(224, 64, 251, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(224, 64, 251, 0.16);
+}
+.mdui-theme-accent-red .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 82, 82, 0.5);
+}
+.mdui-theme-accent-red .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FF5252;
+}
+.mdui-theme-accent-red .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-red .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 82, 82, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 82, 82, 0.16);
+}
+.mdui-theme-accent-teal .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(100, 255, 218, 0.5);
+}
+.mdui-theme-accent-teal .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #64FFDA;
+}
+.mdui-theme-accent-teal .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-teal .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(100, 255, 218, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(100, 255, 218, 0.16);
+}
+.mdui-theme-accent-yellow .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 255, 0, 0.5);
+}
+.mdui-theme-accent-yellow .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FFFF00;
+}
+.mdui-theme-accent-yellow .mdui-switch:active input[type="checkbox"]:checked:not(:disabled) + .mdui-switch-icon::before,
+.mdui-theme-accent-yellow .mdui-switch input[type="checkbox"]:focus:checked:not(:disabled) + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 255, 0, 0.16);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 255, 0, 0.16);
+}
+/**
+ * =============================================================================
+ * ************   Radio dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-switch-icon {
+  background-color: rgba(255, 255, 255, 0.3);
+}
+.mdui-theme-layout-dark .mdui-switch-icon::before {
+  background-color: #BDBDBD;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-amber .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 229, 127, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-amber .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FFE57F;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(130, 177, 255, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #82B1FF;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-cyan .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(132, 255, 255, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-cyan .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #84FFFF;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-deep-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 158, 128, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-deep-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FF9E80;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-deep-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(179, 136, 255, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-deep-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #B388FF;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(185, 246, 202, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #B9F6CA;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-indigo .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(140, 158, 255, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-indigo .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #8C9EFF;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-light-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(128, 216, 255, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-light-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #80D8FF;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-light-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(204, 255, 144, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-light-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #CCFF90;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-lime .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(244, 255, 129, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-lime .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #F4FF81;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 209, 128, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FFD180;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-pink .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 128, 171, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-pink .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FF80AB;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(234, 128, 252, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #EA80FC;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-red .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 138, 128, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-red .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FF8A80;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-teal .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(167, 255, 235, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-teal .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #A7FFEB;
+}
+.mdui-theme-layout-dark.mdui-theme-accent-yellow .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+  background-color: rgba(255, 255, 141, 0.5);
+}
+.mdui-theme-layout-dark.mdui-theme-accent-yellow .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+  background-color: #FFFF8D;
+}
+.mdui-theme-layout-dark .mdui-switch:active input[type="checkbox"] + .mdui-switch-icon::before,
+.mdui-theme-layout-dark .mdui-switch input[type="checkbox"]:focus + .mdui-switch-icon::before {
+  -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 255, 255, 0.1);
+          box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 255, 255, 0.1);
+}
+.mdui-theme-layout-dark .mdui-switch input[type="checkbox"]:disabled + .mdui-switch-icon {
+  background-color: rgba(255, 255, 255, 0.1) !important;
+}
+.mdui-theme-layout-dark .mdui-switch input[type="checkbox"]:disabled + .mdui-switch-icon::before {
+  background-color: #424242 !important;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-switch-icon {
+    background-color: rgba(255, 255, 255, 0.3);
+  }
+  .mdui-theme-layout-auto .mdui-switch-icon::before {
+    background-color: #BDBDBD;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-amber .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(255, 229, 127, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-amber .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #FFE57F;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(130, 177, 255, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #82B1FF;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-cyan .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(132, 255, 255, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-cyan .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #84FFFF;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-deep-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(255, 158, 128, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-deep-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #FF9E80;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-deep-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(179, 136, 255, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-deep-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #B388FF;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(185, 246, 202, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #B9F6CA;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-indigo .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(140, 158, 255, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-indigo .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #8C9EFF;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-light-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(128, 216, 255, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-light-blue .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #80D8FF;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-light-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(204, 255, 144, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-light-green .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #CCFF90;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-lime .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(244, 255, 129, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-lime .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #F4FF81;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(255, 209, 128, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-orange .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #FFD180;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-pink .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(255, 128, 171, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-pink .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #FF80AB;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(234, 128, 252, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-purple .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #EA80FC;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-red .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(255, 138, 128, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-red .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #FF8A80;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-teal .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(167, 255, 235, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-teal .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #A7FFEB;
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-yellow .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon {
+    background-color: rgba(255, 255, 141, 0.5);
+  }
+  .mdui-theme-layout-auto.mdui-theme-accent-yellow .mdui-switch input[type="checkbox"]:checked + .mdui-switch-icon::before {
+    background-color: #FFFF8D;
+  }
+  .mdui-theme-layout-auto .mdui-switch:active input[type="checkbox"] + .mdui-switch-icon::before,
+  .mdui-theme-layout-auto .mdui-switch input[type="checkbox"]:focus + .mdui-switch-icon::before {
+    -webkit-box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 255, 255, 0.1);
+            box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 0 15px rgba(255, 255, 255, 0.1);
+  }
+  .mdui-theme-layout-auto .mdui-switch input[type="checkbox"]:disabled + .mdui-switch-icon {
+    background-color: rgba(255, 255, 255, 0.1) !important;
+  }
+  .mdui-theme-layout-auto .mdui-switch input[type="checkbox"]:disabled + .mdui-switch-icon::before {
+    background-color: #424242 !important;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Slider 滑块   ************
+ * =============================================================================
+ */
+.mdui-slider {
+  position: relative;
+  display: block;
+  width: 100%;
+  height: 36px;
+}
+.mdui-slider input[type="range"] {
+  position: absolute;
+  top: 50%;
+  left: 0;
+  z-index: 2;
+  width: 100%;
+  height: 20px;
+  margin-top: -10px;
+  cursor: pointer;
+  opacity: 0;
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+}
+.mdui-slider-track,
+.mdui-slider-fill {
+  position: absolute;
+  top: 50%;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  height: 2px;
+  margin-top: -1px;
+}
+.mdui-slider-track::before,
+.mdui-slider-fill::before {
+  display: block;
+  width: 100%;
+  height: 100%;
+  content: ' ';
+}
+/* 轨道 */
+.mdui-slider-track {
+  right: 0;
+}
+.mdui-slider-track::before {
+  background-color: #bdbdbd;
+  -webkit-transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+/* 已滑动部分 */
+.mdui-slider-fill {
+  left: 0;
+}
+.mdui-slider-fill::before {
+  background-color: #FF4081;
+}
+/* 滑块 */
+.mdui-slider-thumb {
+  position: absolute;
+  top: 50%;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 12px;
+  height: 12px;
+  margin-top: -6px;
+  background-color: #FF4081;
+  border: 2px solid #FF4081;
+  border-radius: 50%;
+  -webkit-transform: translate(-50%);
+          transform: translate(-50%);
+  -webkit-transition: background 0.45s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.45s cubic-bezier(0.4, 0, 0.2, 1), border-radius 0.2s cubic-bezier(0.4, 0, 0.2, 1), -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: background 0.45s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.45s cubic-bezier(0.4, 0, 0.2, 1), border-radius 0.2s cubic-bezier(0.4, 0, 0.2, 1), -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: background 0.45s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.45s cubic-bezier(0.4, 0, 0.2, 1), transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), border-radius 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: background 0.45s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.45s cubic-bezier(0.4, 0, 0.2, 1), transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), border-radius 0.2s cubic-bezier(0.4, 0, 0.2, 1), -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: background, border-color, transform, border-radius;
+}
+/**
+ * =============================================================================
+ * ************   Slider 强调色   ************
+ * =============================================================================
+ */
+.mdui-theme-accent-amber .mdui-slider-fill::before {
+  background-color: #FFD740;
+}
+.mdui-theme-accent-amber .mdui-slider-thumb {
+  background-color: #FFD740;
+  border: 2px solid #FFD740;
+}
+.mdui-theme-accent-blue .mdui-slider-fill::before {
+  background-color: #448AFF;
+}
+.mdui-theme-accent-blue .mdui-slider-thumb {
+  background-color: #448AFF;
+  border: 2px solid #448AFF;
+}
+.mdui-theme-accent-cyan .mdui-slider-fill::before {
+  background-color: #18FFFF;
+}
+.mdui-theme-accent-cyan .mdui-slider-thumb {
+  background-color: #18FFFF;
+  border: 2px solid #18FFFF;
+}
+.mdui-theme-accent-deep-orange .mdui-slider-fill::before {
+  background-color: #FF6E40;
+}
+.mdui-theme-accent-deep-orange .mdui-slider-thumb {
+  background-color: #FF6E40;
+  border: 2px solid #FF6E40;
+}
+.mdui-theme-accent-deep-purple .mdui-slider-fill::before {
+  background-color: #7C4DFF;
+}
+.mdui-theme-accent-deep-purple .mdui-slider-thumb {
+  background-color: #7C4DFF;
+  border: 2px solid #7C4DFF;
+}
+.mdui-theme-accent-green .mdui-slider-fill::before {
+  background-color: #69F0AE;
+}
+.mdui-theme-accent-green .mdui-slider-thumb {
+  background-color: #69F0AE;
+  border: 2px solid #69F0AE;
+}
+.mdui-theme-accent-indigo .mdui-slider-fill::before {
+  background-color: #536DFE;
+}
+.mdui-theme-accent-indigo .mdui-slider-thumb {
+  background-color: #536DFE;
+  border: 2px solid #536DFE;
+}
+.mdui-theme-accent-light-blue .mdui-slider-fill::before {
+  background-color: #40C4FF;
+}
+.mdui-theme-accent-light-blue .mdui-slider-thumb {
+  background-color: #40C4FF;
+  border: 2px solid #40C4FF;
+}
+.mdui-theme-accent-light-green .mdui-slider-fill::before {
+  background-color: #B2FF59;
+}
+.mdui-theme-accent-light-green .mdui-slider-thumb {
+  background-color: #B2FF59;
+  border: 2px solid #B2FF59;
+}
+.mdui-theme-accent-lime .mdui-slider-fill::before {
+  background-color: #EEFF41;
+}
+.mdui-theme-accent-lime .mdui-slider-thumb {
+  background-color: #EEFF41;
+  border: 2px solid #EEFF41;
+}
+.mdui-theme-accent-orange .mdui-slider-fill::before {
+  background-color: #FFAB40;
+}
+.mdui-theme-accent-orange .mdui-slider-thumb {
+  background-color: #FFAB40;
+  border: 2px solid #FFAB40;
+}
+.mdui-theme-accent-pink .mdui-slider-fill::before {
+  background-color: #FF4081;
+}
+.mdui-theme-accent-pink .mdui-slider-thumb {
+  background-color: #FF4081;
+  border: 2px solid #FF4081;
+}
+.mdui-theme-accent-purple .mdui-slider-fill::before {
+  background-color: #E040FB;
+}
+.mdui-theme-accent-purple .mdui-slider-thumb {
+  background-color: #E040FB;
+  border: 2px solid #E040FB;
+}
+.mdui-theme-accent-red .mdui-slider-fill::before {
+  background-color: #FF5252;
+}
+.mdui-theme-accent-red .mdui-slider-thumb {
+  background-color: #FF5252;
+  border: 2px solid #FF5252;
+}
+.mdui-theme-accent-teal .mdui-slider-fill::before {
+  background-color: #64FFDA;
+}
+.mdui-theme-accent-teal .mdui-slider-thumb {
+  background-color: #64FFDA;
+  border: 2px solid #64FFDA;
+}
+.mdui-theme-accent-yellow .mdui-slider-fill::before {
+  background-color: #FFFF00;
+}
+.mdui-theme-accent-yellow .mdui-slider-thumb {
+  background-color: #FFFF00;
+  border: 2px solid #FFFF00;
+}
+/**
+ * =============================================================================
+ * ============   Slider 的不同状态   ============
+ * =============================================================================
+ */
+/* 鼠标按下状态 */
+.mdui-slider-focus .mdui-slider-track::before {
+  background-color: #9e9e9e;
+}
+.mdui-slider-focus .mdui-slider-thumb {
+  -webkit-transform: translate(-50%) scale(1.6);
+          transform: translate(-50%) scale(1.6);
+}
+/* 滑块值为 0 */
+.mdui-slider-zero .mdui-slider-thumb {
+  background-color: #fff;
+  border-color: #bdbdbd;
+}
+/* 滑块值为 0,且鼠标按下 */
+.mdui-slider-zero.mdui-slider-focus .mdui-slider-thumb {
+  border-color: #9e9e9e;
+}
+/* 禁用状态 */
+.mdui-slider-disabled input[type="range"] {
+  cursor: default;
+}
+.mdui-slider-disabled .mdui-slider-track::before {
+  background-color: #bdbdbd;
+}
+.mdui-slider-disabled .mdui-slider-fill::before {
+  background-color: #bdbdbd;
+}
+.mdui-slider-disabled .mdui-slider-thumb {
+  background-color: #bdbdbd;
+  border-color: transparent !important;
+  -webkit-transform: translate(-50%) scale(0.72);
+          transform: translate(-50%) scale(0.72);
+}
+/**
+ * =============================================================================
+ * ============   间续型滑块   ============
+ * =============================================================================
+ */
+.mdui-slider-discrete .mdui-slider-thumb {
+  width: 30px;
+  height: 30px;
+  margin-top: -15px;
+  margin-left: -15px;
+  border: none;
+  -webkit-transform: rotate(-45deg) scale(0.4);
+          transform: rotate(-45deg) scale(0.4);
+}
+.mdui-slider-discrete .mdui-slider-thumb span {
+  position: absolute;
+  top: 9px;
+  left: -1px;
+  width: 100%;
+  color: #fff;
+  font-size: 12px;
+  text-align: center;
+  -webkit-transform: rotate(45deg);
+          transform: rotate(45deg);
+  opacity: 0;
+  -webkit-transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+}
+.mdui-slider-discrete.mdui-slider-focus .mdui-slider-thumb {
+  border-radius: 15px 15px 15px 0;
+  -webkit-transform: rotate(-45deg) scale(1) translate(22px, -22px);
+          transform: rotate(-45deg) scale(1) translate(22px, -22px);
+}
+.mdui-slider-discrete.mdui-slider-focus .mdui-slider-thumb span {
+  opacity: 1;
+}
+.mdui-slider-discrete.mdui-slider-zero .mdui-slider-thumb {
+  background-color: #323232;
+}
+.mdui-slider-discrete.mdui-slider-zero.mdui-slider-focus .mdui-slider-thumb {
+  background-color: #bdbdbd;
+}
+.mdui-slider-discrete.mdui-slider-disabled .mdui-slider-thumb {
+  -webkit-transform: rotate(-45deg) scale(0.288);
+          transform: rotate(-45deg) scale(0.288);
+}
+.mdui-slider-discrete.mdui-slider-zero.mdui-slider-disabled .mdui-slider-thumb {
+  background-color: #bdbdbd;
+}
+/**
+ * =============================================================================
+ * ************   Slider dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-slider-track::before {
+  background-color: #4c4c4c;
+}
+.mdui-theme-layout-dark .mdui-slider-focus .mdui-slider-track::before {
+  background-color: #4c4c4c;
+}
+.mdui-theme-layout-dark .mdui-slider-zero .mdui-slider-thumb {
+  background-color: #303030;
+  border-color: #4c4c4c;
+}
+.mdui-theme-layout-dark .mdui-slider-zero.mdui-slider-focus .mdui-slider-thumb {
+  border-color: #4c4c4c;
+}
+.mdui-theme-layout-dark .mdui-slider-disabled .mdui-slider-track::before {
+  background-color: #4c4c4c;
+}
+.mdui-theme-layout-dark .mdui-slider-disabled .mdui-slider-fill::before {
+  background-color: #4c4c4c;
+}
+.mdui-theme-layout-dark .mdui-slider-disabled .mdui-slider-thumb {
+  background-color: #4c4c4c;
+}
+.mdui-theme-layout-dark .mdui-slider-discrete.mdui-slider-zero .mdui-slider-thumb {
+  background-color: #fefefe;
+}
+.mdui-theme-layout-dark .mdui-slider-discrete.mdui-slider-zero.mdui-slider-focus .mdui-slider-thumb {
+  background-color: #5c5c5c;
+}
+.mdui-theme-layout-dark .mdui-slider-discrete.mdui-slider-zero.mdui-slider-disabled .mdui-slider-thumb {
+  background-color: #4c4c4c;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-slider-track::before {
+    background-color: #4c4c4c;
+  }
+  .mdui-theme-layout-auto .mdui-slider-focus .mdui-slider-track::before {
+    background-color: #4c4c4c;
+  }
+  .mdui-theme-layout-auto .mdui-slider-zero .mdui-slider-thumb {
+    background-color: #303030;
+    border-color: #4c4c4c;
+  }
+  .mdui-theme-layout-auto .mdui-slider-zero.mdui-slider-focus .mdui-slider-thumb {
+    border-color: #4c4c4c;
+  }
+  .mdui-theme-layout-auto .mdui-slider-disabled .mdui-slider-track::before {
+    background-color: #4c4c4c;
+  }
+  .mdui-theme-layout-auto .mdui-slider-disabled .mdui-slider-fill::before {
+    background-color: #4c4c4c;
+  }
+  .mdui-theme-layout-auto .mdui-slider-disabled .mdui-slider-thumb {
+    background-color: #4c4c4c;
+  }
+  .mdui-theme-layout-auto .mdui-slider-discrete.mdui-slider-zero .mdui-slider-thumb {
+    background-color: #fefefe;
+  }
+  .mdui-theme-layout-auto .mdui-slider-discrete.mdui-slider-zero.mdui-slider-focus .mdui-slider-thumb {
+    background-color: #5c5c5c;
+  }
+  .mdui-theme-layout-auto .mdui-slider-discrete.mdui-slider-zero.mdui-slider-disabled .mdui-slider-thumb {
+    background-color: #4c4c4c;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Button 按钮   ************
+ * =============================================================================
+ */
+/* 默认为 Flat 扁平按钮 */
+.mdui-btn,
+.mdui-fab {
+  position: relative;
+  display: inline-block;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  min-width: 88px;
+  height: 36px;
+  margin: 0;
+  padding: 0 16px;
+  overflow: hidden;
+  color: inherit;
+  font-weight: 500;
+  font-size: 14px;
+  line-height: 36px;
+  letter-spacing: 0.04em;
+  white-space: nowrap;
+  text-align: center;
+  text-transform: uppercase;
+  text-decoration: none;
+  vertical-align: middle;
+  background: transparent;
+  border: none;
+  border-radius: 2px;
+  outline: none;
+  cursor: pointer;
+  -webkit-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1);
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1);
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1);
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), -webkit-box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1);
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  -ms-touch-action: manipulation;
+      touch-action: manipulation;
+  will-change: box-shadow;
+  zoom: 1;
+  -webkit-user-drag: none;
+}
+.mdui-btn:hover,
+.mdui-fab:hover {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+.mdui-btn:not(.mdui-ripple):active,
+.mdui-fab:not(.mdui-ripple):active {
+  background-color: rgba(0, 0, 0, 0.165);
+}
+.mdui-btn[class*="mdui-color-"]:hover,
+.mdui-fab[class*="mdui-color-"]:hover {
+  opacity: 0.87;
+}
+.mdui-btn:not(.mdui-ripple)[class*="mdui-color-"]:active,
+.mdui-fab:not(.mdui-ripple)[class*="mdui-color-"]:active {
+  opacity: 0.76;
+}
+/* 按钮内的图标 */
+.mdui-btn .mdui-icon-left,
+.mdui-btn .mdui-icon-right,
+.mdui-btn .mdui-icon-left::before,
+.mdui-btn .mdui-icon-right::before {
+  height: inherit;
+  font-size: 1.3em;
+  line-height: inherit;
+}
+.mdui-btn .mdui-icon-left {
+  float: left;
+  margin-right: 0.4em;
+}
+.mdui-btn .mdui-icon-right {
+  float: right;
+  margin-left: 0.4em;
+}
+input.mdui-btn[type="submit"] {
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+}
+/* Raised button 浮动按钮 */
+.mdui-btn-raised {
+  -webkit-box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+}
+.mdui-btn-raised:hover {
+  -webkit-box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
+}
+.mdui-btn-raised:active {
+  -webkit-box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+}
+/* 禁用按钮 */
+.mdui-btn[disabled],
+.mdui-fab[disabled],
+.mdui-btn[disabled]:hover,
+.mdui-fab[disabled]:hover,
+.mdui-btn[disabled]:active,
+.mdui-fab[disabled]:active,
+.mdui-btn[disabled]:focus,
+.mdui-fab[disabled]:focus {
+  color: rgba(0, 0, 0, 0.26) !important;
+  background-color: transparent !important;
+  cursor: default !important;
+  opacity: 1 !important;
+  -webkit-box-shadow: none !important;
+          box-shadow: none !important;
+}
+.mdui-btn[disabled] .mdui-icon,
+.mdui-fab[disabled] .mdui-icon,
+.mdui-btn[disabled]:hover .mdui-icon,
+.mdui-fab[disabled]:hover .mdui-icon,
+.mdui-btn[disabled]:active .mdui-icon,
+.mdui-fab[disabled]:active .mdui-icon,
+.mdui-btn[disabled]:focus .mdui-icon,
+.mdui-fab[disabled]:focus .mdui-icon {
+  color: rgba(0, 0, 0, 0.26) !important;
+}
+/* 禁用状态浮动按钮和浮动操作按钮 */
+.mdui-btn-raised[disabled],
+.mdui-fab[disabled],
+.mdui-btn-raised[disabled]:hover,
+.mdui-fab[disabled]:hover,
+.mdui-btn-raised[disabled]:active,
+.mdui-fab[disabled]:active,
+.mdui-btn-raised[disabled]:focus,
+.mdui-fab[disabled]:focus {
+  background-color: rgba(0, 0, 0, 0.12) !important;
+  -webkit-box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12) !important;
+          box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12) !important;
+}
+/* 加粗按钮文本 */
+.mdui-btn-bold {
+  font-weight: bold;
+}
+/* 图标按钮 */
+.mdui-btn-icon {
+  width: 36px;
+  min-width: 36px;
+  height: 36px;
+  margin-right: 0;
+  margin-left: 0;
+  padding: 0;
+  overflow: hidden;
+  font-size: 24px;
+  line-height: normal;
+  border-radius: 50%;
+}
+.mdui-btn-icon .mdui-icon {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 24px;
+  line-height: 24px;
+  -webkit-transform: translate(-12px, -12px);
+          transform: translate(-12px, -12px);
+}
+.mdui-btn-icon.mdui-ripple {
+  -webkit-transform: translateZ(0);
+          transform: translateZ(0);
+}
+/* 按钮 100% 宽度 */
+.mdui-btn-block {
+  display: block;
+  width: 100%;
+}
+/* 密集型按钮 */
+.mdui-btn-dense {
+  height: 32px;
+  font-size: 13px;
+  line-height: 32px;
+}
+.mdui-btn-dense.mdui-btn-icon {
+  width: 32px;
+  min-width: 32px;
+}
+/* 按钮组 */
+.mdui-btn-group {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+.mdui-btn-group .mdui-btn {
+  float: left;
+  min-width: inherit;
+  padding: 0 12px;
+  color: rgba(0, 0, 0, 0.54);
+  border-radius: 0;
+}
+.mdui-btn-group .mdui-btn::before {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  border-left: 1px solid transparent;
+  content: ' ';
+}
+.mdui-btn-group .mdui-btn:first-child {
+  border-top-left-radius: 2px;
+  border-bottom-left-radius: 2px;
+}
+.mdui-btn-group .mdui-btn:first-child::before {
+  border-left: none;
+}
+.mdui-btn-group .mdui-btn:last-child {
+  border-top-right-radius: 2px;
+  border-bottom-right-radius: 2px;
+}
+.mdui-btn-group .mdui-btn.mdui-btn-active {
+  color: rgba(0, 0, 0, 0.87);
+  background-color: rgba(0, 0, 0, 0.215);
+}
+.mdui-btn-group .mdui-btn.mdui-btn-active + .mdui-btn-active::before {
+  border-left: 1px solid rgba(0, 0, 0, 0.145);
+}
+/**
+ * =============================================================================
+ * ************   Button dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-btn:hover,
+.mdui-theme-layout-dark .mdui-fab:hover {
+  background-color: rgba(255, 255, 255, 0.1);
+}
+.mdui-theme-layout-dark .mdui-btn:not(.mdui-ripple):active,
+.mdui-theme-layout-dark .mdui-fab:not(.mdui-ripple):active {
+  background-color: rgba(255, 255, 255, 0.165);
+}
+.mdui-theme-layout-dark .mdui-btn[class*="mdui-color-"]:hover,
+.mdui-theme-layout-dark .mdui-fab[class*="mdui-color-"]:hover {
+  opacity: 0.87;
+}
+.mdui-theme-layout-dark .mdui-btn:not(.mdui-ripple)[class*="mdui-color-"]:active,
+.mdui-theme-layout-dark .mdui-fab:not(.mdui-ripple)[class*="mdui-color-"]:active {
+  opacity: 0.76;
+}
+.mdui-theme-layout-dark .mdui-btn[disabled],
+.mdui-theme-layout-dark .mdui-fab[disabled],
+.mdui-theme-layout-dark .mdui-btn[disabled]:hover,
+.mdui-theme-layout-dark .mdui-fab[disabled]:hover,
+.mdui-theme-layout-dark .mdui-btn[disabled]:active,
+.mdui-theme-layout-dark .mdui-fab[disabled]:active,
+.mdui-theme-layout-dark .mdui-btn[disabled]:focus,
+.mdui-theme-layout-dark .mdui-fab[disabled]:focus {
+  color: rgba(255, 255, 255, 0.3) !important;
+  background-color: transparent !important;
+}
+.mdui-theme-layout-dark .mdui-btn[disabled] .mdui-icon,
+.mdui-theme-layout-dark .mdui-fab[disabled] .mdui-icon,
+.mdui-theme-layout-dark .mdui-btn[disabled]:hover .mdui-icon,
+.mdui-theme-layout-dark .mdui-fab[disabled]:hover .mdui-icon,
+.mdui-theme-layout-dark .mdui-btn[disabled]:active .mdui-icon,
+.mdui-theme-layout-dark .mdui-fab[disabled]:active .mdui-icon,
+.mdui-theme-layout-dark .mdui-btn[disabled]:focus .mdui-icon,
+.mdui-theme-layout-dark .mdui-fab[disabled]:focus .mdui-icon {
+  color: rgba(255, 255, 255, 0.3) !important;
+}
+.mdui-theme-layout-dark .mdui-btn-raised[disabled],
+.mdui-theme-layout-dark .mdui-fab[disabled],
+.mdui-theme-layout-dark .mdui-btn-raised[disabled]:hover,
+.mdui-theme-layout-dark .mdui-fab[disabled]:hover,
+.mdui-theme-layout-dark .mdui-btn-raised[disabled]:active,
+.mdui-theme-layout-dark .mdui-fab[disabled]:active,
+.mdui-theme-layout-dark .mdui-btn-raised[disabled]:focus,
+.mdui-theme-layout-dark .mdui-fab[disabled]:focus {
+  background-color: rgba(255, 255, 255, 0.12) !important;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-btn:hover,
+  .mdui-theme-layout-auto .mdui-fab:hover {
+    background-color: rgba(255, 255, 255, 0.1);
+  }
+  .mdui-theme-layout-auto .mdui-btn:not(.mdui-ripple):active,
+  .mdui-theme-layout-auto .mdui-fab:not(.mdui-ripple):active {
+    background-color: rgba(255, 255, 255, 0.165);
+  }
+  .mdui-theme-layout-auto .mdui-btn[class*="mdui-color-"]:hover,
+  .mdui-theme-layout-auto .mdui-fab[class*="mdui-color-"]:hover {
+    opacity: 0.87;
+  }
+  .mdui-theme-layout-auto .mdui-btn:not(.mdui-ripple)[class*="mdui-color-"]:active,
+  .mdui-theme-layout-auto .mdui-fab:not(.mdui-ripple)[class*="mdui-color-"]:active {
+    opacity: 0.76;
+  }
+  .mdui-theme-layout-auto .mdui-btn[disabled],
+  .mdui-theme-layout-auto .mdui-fab[disabled],
+  .mdui-theme-layout-auto .mdui-btn[disabled]:hover,
+  .mdui-theme-layout-auto .mdui-fab[disabled]:hover,
+  .mdui-theme-layout-auto .mdui-btn[disabled]:active,
+  .mdui-theme-layout-auto .mdui-fab[disabled]:active,
+  .mdui-theme-layout-auto .mdui-btn[disabled]:focus,
+  .mdui-theme-layout-auto .mdui-fab[disabled]:focus {
+    color: rgba(255, 255, 255, 0.3) !important;
+    background-color: transparent !important;
+  }
+  .mdui-theme-layout-auto .mdui-btn[disabled] .mdui-icon,
+  .mdui-theme-layout-auto .mdui-fab[disabled] .mdui-icon,
+  .mdui-theme-layout-auto .mdui-btn[disabled]:hover .mdui-icon,
+  .mdui-theme-layout-auto .mdui-fab[disabled]:hover .mdui-icon,
+  .mdui-theme-layout-auto .mdui-btn[disabled]:active .mdui-icon,
+  .mdui-theme-layout-auto .mdui-fab[disabled]:active .mdui-icon,
+  .mdui-theme-layout-auto .mdui-btn[disabled]:focus .mdui-icon,
+  .mdui-theme-layout-auto .mdui-fab[disabled]:focus .mdui-icon {
+    color: rgba(255, 255, 255, 0.3) !important;
+  }
+  .mdui-theme-layout-auto .mdui-btn-raised[disabled],
+  .mdui-theme-layout-auto .mdui-fab[disabled],
+  .mdui-theme-layout-auto .mdui-btn-raised[disabled]:hover,
+  .mdui-theme-layout-auto .mdui-fab[disabled]:hover,
+  .mdui-theme-layout-auto .mdui-btn-raised[disabled]:active,
+  .mdui-theme-layout-auto .mdui-fab[disabled]:active,
+  .mdui-theme-layout-auto .mdui-btn-raised[disabled]:focus,
+  .mdui-theme-layout-auto .mdui-fab[disabled]:focus {
+    background-color: rgba(255, 255, 255, 0.12) !important;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Fab 浮动操作按钮   ************
+ * =============================================================================
+ */
+/* 浮动操作按钮 */
+.mdui-fab {
+  width: 56px;
+  min-width: 56px;
+  height: 56px;
+  margin: auto;
+  padding: 0 !important;
+  overflow: hidden;
+  font-size: 24px;
+  line-height: normal !important;
+  border-radius: 50%;
+  -webkit-box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12);
+}
+.mdui-fab:hover {
+  -webkit-box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+}
+.mdui-fab:active {
+  -webkit-box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 12px 17px 2px rgba(0, 0, 0, 0.14), 0 5px 22px 4px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 12px 17px 2px rgba(0, 0, 0, 0.14), 0 5px 22px 4px rgba(0, 0, 0, 0.12);
+}
+.mdui-fab .mdui-icon {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 24px;
+  margin-top: 16px;
+  margin-left: 16px;
+  line-height: 24px;
+}
+/* mini 型浮动操作按钮 */
+.mdui-fab-mini {
+  width: 40px;
+  min-width: 40px;
+  height: 40px;
+}
+.mdui-fab-mini .mdui-icon {
+  margin-top: 8px;
+  margin-left: 8px;
+}
+/* 固定到右下角的 FAB 按钮 */
+.mdui-fab-fixed,
+.mdui-fab-wrapper {
+  position: fixed !important;
+  /* 手机平板上距离屏幕右下角 16px */
+  right: 16px;
+  bottom: 16px;
+}
+@media (min-width: 1024px) {
+  .mdui-fab-fixed,
+  .mdui-fab-wrapper {
+    /* 电脑上距离屏幕右下角 24px */
+    right: 24px;
+    bottom: 24px;
+  }
+}
+/* 含菜单的浮动操作按钮 */
+.mdui-fab-wrapper {
+  position: relative;
+  z-index: 4000;
+  width: 56px;
+  height: 56px;
+  padding-top: 8px;
+  text-align: center;
+}
+.mdui-fab-wrapper > .mdui-fab .mdui-icon:not(.mdui-fab-opened) {
+  opacity: 1;
+  -webkit-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: opacity, transform;
+}
+.mdui-fab-wrapper > .mdui-fab .mdui-icon.mdui-fab-opened {
+  -webkit-transform: rotate(225deg);
+          transform: rotate(225deg);
+  opacity: 0;
+  -webkit-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: opacity, transform;
+}
+.mdui-fab-wrapper > .mdui-fab.mdui-fab-opened .mdui-icon:not(.mdui-fab-opened) {
+  -webkit-transform: rotate(225deg);
+          transform: rotate(225deg);
+  opacity: 0;
+}
+.mdui-fab-wrapper > .mdui-fab.mdui-fab-opened .mdui-icon.mdui-fab-opened {
+  -webkit-transform: rotate(360deg);
+          transform: rotate(360deg);
+  opacity: 1;
+}
+.mdui-fab-wrapper > .mdui-fab-mini {
+  margin-top: 8px;
+}
+.mdui-fab-wrapper .mdui-fab-dial {
+  position: absolute;
+  right: 0;
+  bottom: 64px;
+  left: 0;
+  height: 0;
+  text-align: center;
+  visibility: visible;
+}
+.mdui-fab-wrapper .mdui-fab-dial .mdui-fab {
+  margin: 8px 0;
+  -webkit-transform: scale(0);
+          transform: scale(0);
+  opacity: 0;
+  -webkit-transition: color 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), -webkit-transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
+  transition: color 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), -webkit-transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), color 0.2s cubic-bezier(0.4, 0, 0.2, 1), transform 150ms cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), color 0.2s cubic-bezier(0.4, 0, 0.2, 1), transform 150ms cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), -webkit-transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
+}
+.mdui-fab-wrapper .mdui-fab-dial.mdui-fab-dial-show .mdui-fab {
+  -webkit-transform: scale(1);
+          transform: scale(1);
+  opacity: 1;
+}
+/* 添加类 .mdui-fab-hide 以动画的形式隐藏按钮 */
+.mdui-fab,
+.mdui-fab-mini,
+.mdui-fab-wrapper {
+  -webkit-transform: scale(1) translateZ(0);
+          transform: scale(1) translateZ(0);
+  -webkit-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), -webkit-transform 0.2s;
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), -webkit-transform 0.2s;
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), transform 0.2s;
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), transform 0.2s, -webkit-box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), -webkit-transform 0.2s;
+  will-change: transform;
+}
+.mdui-fab.mdui-fab-hide,
+.mdui-fab-mini.mdui-fab-hide,
+.mdui-fab-wrapper.mdui-fab-hide {
+  -webkit-transform: scale(0) translateZ(0);
+          transform: scale(0) translateZ(0);
+}
+/**
+ * =============================================================================
+ * ************   Select 下拉选择   ************
+ * =============================================================================
+ */
+.mdui-select {
+  position: relative;
+  display: inline-block;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  max-width: 100%;
+  height: 36px;
+  padding-right: 24px;
+  padding-left: 0;
+  font-size: 16px;
+  font-family: Roboto, Noto, Helvetica, Arial, sans-serif;
+  vertical-align: middle;
+  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='M-.003 2.5l5 5 5-5h-10z' opacity='.54'/%3E%3C/svg%3E");
+  background-repeat: no-repeat;
+  background-position: right center;
+  border: none;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
+  outline: none;
+  cursor: pointer;
+  -webkit-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+          transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+  -webkit-transition-duration: 0.2s;
+          transition-duration: 0.2s;
+  -webkit-transition-property: background-color, background-position-x, -webkit-box-shadow;
+  transition-property: background-color, background-position-x, -webkit-box-shadow;
+  transition-property: background-color, box-shadow, background-position-x;
+  transition-property: background-color, box-shadow, background-position-x, -webkit-box-shadow;
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  will-change: background-color, box-shadow, background-position-x;
+}
+.mdui-select.mdui-select-open {
+  border-bottom: none;
+}
+.mdui-select-position-top {
+  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='M10.003 7.5l-5-5-5 5h10z' opacity='.54'/%3E%3C/svg%3E");
+}
+/* 底部和顶部菜单的样式 */
+.mdui-select-open.mdui-select-position-top,
+.mdui-select-open.mdui-select-position-bottom {
+  z-index: 99999;
+  background-color: #fff;
+  /* stylelint-disable-next-line */
+  background-position-x: calc(100% - 12px);
+  border-radius: 2px;
+}
+.mdui-select-open.mdui-select-position-top {
+  border-top: 1px solid rgba(0, 0, 0, 0.12);
+  border-bottom: 2px solid transparent;
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  -webkit-box-shadow: 0 10px 10px -3px rgba(0, 0, 0, 0.2), 0 0 14px 1px rgba(0, 0, 0, 0.14), 0 -7px 24px 2px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 10px 10px -3px rgba(0, 0, 0, 0.2), 0 0 14px 1px rgba(0, 0, 0, 0.14), 0 -7px 24px 2px rgba(0, 0, 0, 0.12);
+}
+.mdui-select-open.mdui-select-position-top .mdui-select-menu {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+  -webkit-box-shadow: 0 -4px 4px -2px rgba(0, 0, 0, 0.06), 8px 0 8px -4px rgba(0, 0, 0, 0.12), -8px 0 8px -4px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 -4px 4px -2px rgba(0, 0, 0, 0.06), 8px 0 8px -4px rgba(0, 0, 0, 0.12), -8px 0 8px -4px rgba(0, 0, 0, 0.12);
+}
+.mdui-select-open.mdui-select-position-bottom {
+  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+  -webkit-box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+}
+.mdui-select-open.mdui-select-position-bottom .mdui-select-menu {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+  -webkit-box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 9px 9px 1px rgba(0, 0, 0, 0.14), 0 8px 8px 2px rgba(0, 0, 0, 0.06);
+          box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 9px 9px 1px rgba(0, 0, 0, 0.14), 0 8px 8px 2px rgba(0, 0, 0, 0.06);
+}
+/* 当前选中项文本 */
+.mdui-select-selected {
+  position: absolute;
+  top: 50%;
+  right: 24px;
+  left: 0;
+  display: block;
+  -webkit-transform: translateY(-50%);
+          transform: translateY(-50%);
+  -webkit-transition: left 0.2s cubic-bezier(0, 0, 0.2, 1);
+  transition: left 0.2s cubic-bezier(0, 0, 0.2, 1);
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-select-open .mdui-select-selected {
+  right: 32px;
+  left: 16px;
+}
+.mdui-select-open.mdui-select-position-auto .mdui-select-selected {
+  visibility: hidden;
+}
+/* 菜单 */
+.mdui-select-menu {
+  position: relative;
+  z-index: 99999;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  height: 36px;
+  margin: 0 -24px 0 0;
+  overflow-y: scroll;
+  color: rgba(0, 0, 0, 0.87);
+  background-color: #fff;
+  border-radius: 2px;
+  -webkit-transform: scale(1, 0);
+          transform: scale(1, 0);
+  visibility: hidden;
+  cursor: default;
+  opacity: 0;
+  -webkit-transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
+          transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
+  -webkit-transition-duration: 0.2s;
+          transition-duration: 0.2s;
+  -webkit-transition-property: opacity, visibility, -webkit-transform;
+  transition-property: opacity, visibility, -webkit-transform;
+  transition-property: transform, opacity, visibility;
+  transition-property: transform, opacity, visibility, -webkit-transform;
+  will-change: transform, opacity, visibility;
+  -webkit-overflow-scrolling: touch;
+  -webkit-box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+}
+.mdui-select-open .mdui-select-menu {
+  overflow-y: hidden;
+  -webkit-transform: scale(1, 1);
+          transform: scale(1, 1);
+  visibility: visible;
+  opacity: 1;
+}
+.mdui-select-closing .mdui-select-menu {
+  overflow-y: hidden;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+  -webkit-transform: scale(1, 1);
+          transform: scale(1, 1);
+  visibility: visible;
+  opacity: 0;
+}
+/* 菜单项 */
+.mdui-select-menu-item {
+  height: 48px;
+  padding: 0 16px;
+  line-height: 48px;
+  cursor: pointer;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-select-menu-item:hover {
+  background-color: #EEEEEE;
+}
+.mdui-select-menu-item:first-child {
+  margin-top: 8px;
+}
+.mdui-select-menu-item:last-child {
+  margin-bottom: 8px;
+}
+.mdui-select-menu-item[disabled] {
+  color: rgba(0, 0, 0, 0.38) !important;
+  cursor: default;
+}
+.mdui-select-menu-item[disabled]:hover {
+  background-color: inherit !important;
+}
+.mdui-select-menu-item[selected] {
+  color: #FF4081;
+}
+/* 原生 select 组件 */
+select.mdui-select {
+  background-color: transparent;
+}
+select.mdui-select option {
+  color: rgba(0, 0, 0, 0.87);
+}
+select.mdui-select::-ms-expand {
+  display: none;
+}
+/* 原生多选 select 组件 */
+select.mdui-select[multiple] {
+  height: auto;
+  padding: 0;
+  font-size: 15px;
+  background-color: #FFF;
+  background-image: none;
+  border: 1px solid rgba(0, 0, 0, 0.38);
+  cursor: default;
+}
+select.mdui-select[multiple] optgroup {
+  margin: 8px 0 0 0;
+  padding: 0 0 0 16px;
+  color: rgba(0, 0, 0, 0.38);
+}
+select.mdui-select[multiple] optgroup:last-child {
+  margin-bottom: 8px;
+}
+select.mdui-select[multiple] optgroup:not(:first-child) {
+  padding-top: 8px;
+  border-top: 1px solid rgba(0, 0, 0, 0.12);
+}
+select.mdui-select[multiple] option {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-align: center;
+      -ms-flex-align: center;
+          align-items: center;
+  height: 32px;
+  margin: 0 0 0 -16px;
+  padding: 0 16px;
+  color: rgba(0, 0, 0, 0.87);
+}
+select.mdui-select[multiple] option:first-child {
+  margin-top: 8px;
+}
+select.mdui-select[multiple] option:last-child {
+  margin-bottom: 8px;
+}
+/**
+ * =============================================================================
+ * ************   Select 强调色   ************
+ * =============================================================================
+ */
+.mdui-theme-accent-amber .mdui-select-menu-item[selected] {
+  color: #FFC107;
+}
+.mdui-theme-accent-blue .mdui-select-menu-item[selected] {
+  color: #2196F3;
+}
+.mdui-theme-accent-cyan .mdui-select-menu-item[selected] {
+  color: #00BCD4;
+}
+.mdui-theme-accent-deep-orange .mdui-select-menu-item[selected] {
+  color: #FF5722;
+}
+.mdui-theme-accent-deep-purple .mdui-select-menu-item[selected] {
+  color: #673AB7;
+}
+.mdui-theme-accent-green .mdui-select-menu-item[selected] {
+  color: #4CAF50;
+}
+.mdui-theme-accent-indigo .mdui-select-menu-item[selected] {
+  color: #3F51B5;
+}
+.mdui-theme-accent-light-blue .mdui-select-menu-item[selected] {
+  color: #03A9F4;
+}
+.mdui-theme-accent-light-green .mdui-select-menu-item[selected] {
+  color: #8BC34A;
+}
+.mdui-theme-accent-lime .mdui-select-menu-item[selected] {
+  color: #CDDC39;
+}
+.mdui-theme-accent-orange .mdui-select-menu-item[selected] {
+  color: #FF9800;
+}
+.mdui-theme-accent-pink .mdui-select-menu-item[selected] {
+  color: #E91E63;
+}
+.mdui-theme-accent-purple .mdui-select-menu-item[selected] {
+  color: #9C27B0;
+}
+.mdui-theme-accent-red .mdui-select-menu-item[selected] {
+  color: #F44336;
+}
+.mdui-theme-accent-teal .mdui-select-menu-item[selected] {
+  color: #009688;
+}
+.mdui-theme-accent-yellow .mdui-select-menu-item[selected] {
+  color: #FFEB3B;
+}
+/**
+ * =============================================================================
+ * ************   Select dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-select {
+  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='M-.003 2.5l5 5 5-5h-10z' fill='%23FFF'/%3E%3C/svg%3E");
+  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
+}
+.mdui-theme-layout-dark .mdui-select-position-top {
+  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='M10.003 7.5l-5-5-5 5h10z' fill='%23FFF'/%3E%3C/svg%3E");
+}
+.mdui-theme-layout-dark .mdui-select-open.mdui-select-position-top,
+.mdui-theme-layout-dark .mdui-select-open.mdui-select-position-bottom {
+  background-color: #424242;
+}
+.mdui-theme-layout-dark .mdui-select-open.mdui-select-position-top {
+  border-top: 1px solid rgba(255, 255, 255, 0.12);
+}
+.mdui-theme-layout-dark .mdui-select-open.mdui-select-position-bottom {
+  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
+}
+.mdui-theme-layout-dark .mdui-select-menu {
+  color: #fff;
+  background-color: #424242;
+}
+.mdui-theme-layout-dark .mdui-select-menu-item:hover {
+  background-color: #616161;
+}
+.mdui-theme-layout-dark .mdui-select-menu-item[disabled] {
+  color: rgba(255, 255, 255, 0.5) !important;
+}
+.mdui-theme-layout-dark select.mdui-select {
+  color: #FFF;
+  background-color: #303030;
+}
+.mdui-theme-layout-dark select.mdui-select option {
+  color: #FFF;
+  background-color: #303030;
+}
+.mdui-theme-layout-dark select.mdui-select[multiple] {
+  border: 1px solid rgba(255, 255, 255, 0.5);
+}
+.mdui-theme-layout-dark select.mdui-select[multiple] optgroup {
+  color: rgba(255, 255, 255, 0.5);
+}
+.mdui-theme-layout-dark select.mdui-select[multiple] optgroup:not(:first-child) {
+  border-top: 1px solid rgba(255, 255, 255, 0.12);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-select {
+    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='M-.003 2.5l5 5 5-5h-10z' fill='%23FFF'/%3E%3C/svg%3E");
+    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
+  }
+  .mdui-theme-layout-auto .mdui-select-position-top {
+    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='M10.003 7.5l-5-5-5 5h10z' fill='%23FFF'/%3E%3C/svg%3E");
+  }
+  .mdui-theme-layout-auto .mdui-select-open.mdui-select-position-top,
+  .mdui-theme-layout-auto .mdui-select-open.mdui-select-position-bottom {
+    background-color: #424242;
+  }
+  .mdui-theme-layout-auto .mdui-select-open.mdui-select-position-top {
+    border-top: 1px solid rgba(255, 255, 255, 0.12);
+  }
+  .mdui-theme-layout-auto .mdui-select-open.mdui-select-position-bottom {
+    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
+  }
+  .mdui-theme-layout-auto .mdui-select-menu {
+    color: #fff;
+    background-color: #424242;
+  }
+  .mdui-theme-layout-auto .mdui-select-menu-item:hover {
+    background-color: #616161;
+  }
+  .mdui-theme-layout-auto .mdui-select-menu-item[disabled] {
+    color: rgba(255, 255, 255, 0.5) !important;
+  }
+  .mdui-theme-layout-auto select.mdui-select {
+    color: #FFF;
+    background-color: #303030;
+  }
+  .mdui-theme-layout-auto select.mdui-select option {
+    color: #FFF;
+    background-color: #303030;
+  }
+  .mdui-theme-layout-auto select.mdui-select[multiple] {
+    border: 1px solid rgba(255, 255, 255, 0.5);
+  }
+  .mdui-theme-layout-auto select.mdui-select[multiple] optgroup {
+    color: rgba(255, 255, 255, 0.5);
+  }
+  .mdui-theme-layout-auto select.mdui-select[multiple] optgroup:not(:first-child) {
+    border-top: 1px solid rgba(255, 255, 255, 0.12);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Toolbar 工具栏   ************
+ * =============================================================================
+ */
+.mdui-toolbar {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-align: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 100%;
+}
+.mdui-toolbar > * {
+  margin: 0 16px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-toolbar[class*="mdui-color-"]:not(.mdui-color-transparent) .mdui-btn:hover {
+  background-color: rgba(255, 255, 255, 0.1);
+}
+.mdui-toolbar[class*="mdui-color-"]:not(.mdui-color-transparent) .mdui-btn:active {
+  background-color: rgba(255, 255, 255, 0.165);
+}
+.mdui-toolbar > a {
+  color: inherit;
+  text-decoration: none;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+}
+.mdui-toolbar > .mdui-btn-icon {
+  width: 48px;
+  min-width: 48px;
+  height: 48px;
+}
+@media (orientation: landscape) and (max-width: 959.9px) {
+  .mdui-toolbar > .mdui-btn-icon {
+    width: 40px;
+    min-width: 40px;
+    height: 40px;
+  }
+}
+.mdui-toolbar > .mdui-btn-icon .mdui-icon {
+  height: 24px;
+  line-height: 24px;
+}
+.mdui-toolbar .mdui-icon {
+  color: inherit;
+}
+.mdui-toolbar-spacer {
+  -webkit-box-flex: 1;
+      -ms-flex-positive: 1;
+          flex-grow: 1;
+  margin: 0;
+}
+/* 手机 */
+.mdui-toolbar {
+  height: 56px;
+  line-height: 56px;
+}
+.mdui-toolbar > .mdui-btn {
+  margin: 0 4px;
+}
+.mdui-toolbar > .mdui-btn + .mdui-btn {
+  margin-left: 0;
+}
+@media (min-width: 600px) {
+  .mdui-appbar .mdui-toolbar {
+    height: 64px;
+    line-height: 64px;
+  }
+  .mdui-appbar .mdui-toolbar > .mdui-btn {
+    margin: 0 8px;
+  }
+  .mdui-appbar .mdui-toolbar > .mdui-btn + .mdui-btn {
+    margin-left: 0;
+  }
+}
+@media (orientation: landscape) and (max-width: 959.9px) {
+  .mdui-appbar .mdui-toolbar {
+    height: 48px;
+    line-height: 48px;
+  }
+  .mdui-appbar .mdui-toolbar > .mdui-btn {
+    margin: 0 4px;
+  }
+  .mdui-appbar .mdui-toolbar > .mdui-btn + .mdui-btn {
+    margin-left: 0;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Appbar 应用栏   ************
+ * =============================================================================
+ */
+.mdui-appbar {
+  z-index: 1000;
+  -webkit-box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
+}
+/* appbar 固定在顶部 */
+.mdui-appbar-fixed {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  -webkit-transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
+          transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
+  -webkit-transition-duration: 0.3s;
+          transition-duration: 0.3s;
+  -webkit-transition-property: left, right;
+  transition-property: left, right;
+  will-change: left, right;
+}
+/* 左侧留出抽屉栏的距离 */
+@media (min-width: 1024px) {
+  .mdui-drawer-body-left .mdui-appbar-inset.mdui-appbar-fixed {
+    left: 240px;
+  }
+}
+@media (min-width: 1024px) {
+  .mdui-drawer-body-right .mdui-appbar-inset.mdui-appbar-fixed {
+    right: 240px;
+  }
+}
+/* 含工具栏 */
+.mdui-appbar-with-toolbar {
+  padding-top: 56px;
+}
+@media (min-width: 600px) {
+  .mdui-appbar-with-toolbar {
+    padding-top: 64px;
+  }
+}
+@media (orientation: landscape) and (max-width: 959.9px) {
+  .mdui-appbar-with-toolbar {
+    padding-top: 48px;
+  }
+}
+/* 含 Tab */
+.mdui-appbar-with-tab {
+  padding-top: 48px;
+}
+/* 含大 Tab  */
+.mdui-appbar-with-tab-larger {
+  padding-top: 72px;
+}
+/* 含工具栏和 Tab */
+.mdui-appbar-with-toolbar.mdui-appbar-with-tab {
+  padding-top: 104px;
+}
+@media (min-width: 600px) {
+  .mdui-appbar-with-toolbar.mdui-appbar-with-tab {
+    padding-top: 112px;
+  }
+}
+@media (orientation: landscape) and (max-width: 959.9px) {
+  .mdui-appbar-with-toolbar.mdui-appbar-with-tab {
+    padding-top: 96px;
+  }
+}
+/* 含工具栏和大 Tab */
+.mdui-appbar-with-toolbar.mdui-appbar-with-tab-larger {
+  padding-top: 128px;
+}
+@media (min-width: 600px) {
+  .mdui-appbar-with-toolbar.mdui-appbar-with-tab-larger {
+    padding-top: 136px;
+  }
+}
+@media (orientation: landscape) and (max-width: 959.9px) {
+  .mdui-appbar-with-toolbar.mdui-appbar-with-tab-larger {
+    padding-top: 120px;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Appbar dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-appbar > [class*="mdui-color-"]:not(.mdui-color-transparent) {
+  color: #fff !important;
+  background-color: #212121 !important;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-appbar > [class*="mdui-color-"]:not(.mdui-color-transparent) {
+    color: #fff !important;
+    background-color: #212121 !important;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Card 卡片   ************
+ * =============================================================================
+ */
+/* 卡片 */
+.mdui-card {
+  position: relative;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  overflow: hidden;
+  color: #000;
+  background-color: #fff;
+  border-radius: 2px;
+  -webkit-box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+}
+/**
+ * ===================== 头部,包含头像、标题、副标题
+ */
+.mdui-card-header {
+  position: relative;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  height: 72px;
+  padding: 16px;
+}
+/* 卡片头部头像 */
+.mdui-card-header-avatar {
+  float: left;
+  width: 40px;
+  height: 40px;
+  border-radius: 50%;
+}
+/* 卡片头部标题 */
+.mdui-card-header-title {
+  display: block;
+  margin-left: 52px;
+  font-weight: 500;
+  font-size: 16px;
+  line-height: 20px;
+  opacity: 0.87;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+/* 卡片头部副标题 */
+.mdui-card-header-subtitle {
+  display: block;
+  margin-left: 52px;
+  font-weight: 400;
+  font-size: 14px;
+  line-height: 20px;
+  opacity: 0.54;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+/**
+ * =========================== 主标题区域
+ */
+.mdui-card-primary {
+  position: relative;
+  padding: 24px 16px 16px 16px;
+}
+/* 主标题区域标题 */
+.mdui-card-primary-title {
+  display: block;
+  font-size: 24px;
+  line-height: 36px;
+  opacity: 0.87;
+}
+/* 主标题区域副标题 */
+.mdui-card-primary-subtitle {
+  display: block;
+  font-size: 14px;
+  line-height: 24px;
+  opacity: 0.54;
+}
+/**
+ * ============================ 内容区域
+ */
+.mdui-card-content {
+  position: relative;
+  padding: 16px;
+  font-size: 14px;
+  line-height: 24px;
+}
+/**
+ * ============================ 卡片菜单
+ */
+.mdui-card-menu {
+  position: absolute;
+  top: 16px;
+  right: 16px;
+  z-index: 1;
+}
+.mdui-card-menu .mdui-btn {
+  margin-left: 8px;
+}
+/**
+ * =========================== 按钮区域
+ */
+.mdui-card-actions {
+  position: relative;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 8px;
+}
+.mdui-card-actions::before,
+.mdui-card-actions::after {
+  display: table;
+  content: ' ';
+}
+.mdui-card-actions::after {
+  clear: both;
+}
+.mdui-card-actions::before,
+.mdui-card-actions::after {
+  display: table;
+  content: ' ';
+}
+.mdui-card-actions::after {
+  clear: both;
+}
+.mdui-card-actions .mdui-btn {
+  max-width: 100%;
+  margin: 0 8px 0 0;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-card-actions .mdui-btn-icon {
+  width: 36px;
+  height: 36px;
+  margin: 0 8px;
+}
+/* 使按钮竖向排列 */
+.mdui-card-actions-stacked .mdui-btn {
+  display: block;
+  margin: 0 0 4px 0;
+}
+.mdui-card-actions-stacked .mdui-btn:last-child {
+  margin: 0;
+}
+/**
+ * ============================= 媒体元素区域
+ */
+.mdui-card-media {
+  position: relative;
+}
+.mdui-card-media img,
+.mdui-card-media video {
+  display: block;
+  width: 100%;
+}
+/* 覆盖在媒体元素上的内容 */
+.mdui-card-media-covered {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  color: #fff;
+  background: rgba(0, 0, 0, 0.2);
+  /* 覆盖在媒体元素上的标题 */
+}
+.mdui-card-media-covered .mdui-card-primary-title {
+  opacity: 1;
+}
+.mdui-card-media-covered .mdui-card-primary-subtitle {
+  opacity: 0.7;
+}
+/* 覆盖在媒体元素顶部 */
+.mdui-card-media-covered-top {
+  top: 0;
+  bottom: auto;
+}
+/* 覆盖层透明 */
+.mdui-card-media-covered-transparent {
+  background: transparent;
+}
+/* 覆盖层渐变 */
+.mdui-card-media-covered-gradient {
+  background: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.26)), to(rgba(0, 0, 0, 0)));
+  background: linear-gradient(to top, rgba(0, 0, 0, 0.26), rgba(0, 0, 0, 0));
+}
+.mdui-card-media-covered-gradient.mdui-card-media-covered-top {
+  background: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.26)), to(rgba(0, 0, 0, 0)));
+  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.26), rgba(0, 0, 0, 0));
+}
+/**
+ * =============================================================================
+ * ************   Card dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-card {
+  color: #fff;
+  background-color: #424242;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-card {
+    color: #fff;
+    background-color: #424242;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Tab   ************
+ * =============================================================================
+ *
+ * 在手机上选项卡始终平分或可滚动,在平板以上的设备上默认左对齐,可以选择居中对齐,或全宽等分
+ */
+/* 选项卡,默认的选项卡为全宽 */
+.mdui-tab {
+  position: relative;
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  min-height: 48px;
+  max-height: 72px;
+  margin: 0 auto;
+  padding: 0;
+  overflow-x: auto;
+  overflow-y: hidden;
+  white-space: nowrap;
+  -webkit-overflow-scrolling: touch;
+}
+.mdui-tab a {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-flex: 1;
+      -ms-flex: 1;
+          flex: 1;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+      -ms-flex-direction: column;
+          flex-direction: column;
+  -webkit-box-align: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-pack: center;
+      -ms-flex-pack: center;
+          justify-content: center;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  min-width: 72px;
+  min-height: 48px;
+  max-height: 72px;
+  padding: 12px;
+  overflow: hidden;
+  color: inherit;
+  font-size: 14px;
+  text-align: center;
+  text-transform: uppercase;
+  text-decoration: none;
+  text-overflow: ellipsis;
+  outline: none;
+  cursor: pointer;
+  opacity: 0.7;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+}
+.mdui-tab a .mdui-icon {
+  opacity: 0.7;
+}
+@media (min-width: 600px) {
+  .mdui-tab a {
+    -webkit-box-flex: 0;
+        -ms-flex: none;
+            flex: none;
+    min-width: 99px;
+    max-width: 264px;
+    padding: 12px 24px;
+  }
+}
+@media (min-width: 1024px) {
+  .mdui-tab a {
+    min-width: 112px;
+  }
+}
+@media (min-width: 1440px) {
+  .mdui-tab a {
+    min-width: 136px;
+  }
+}
+@media (min-width: 1920px) {
+  .mdui-tab a {
+    min-width: 160px;
+  }
+}
+.mdui-tab a label {
+  display: block;
+  width: 100%;
+  cursor: pointer;
+}
+.mdui-tab a .mdui-icon + label {
+  margin-top: 8px;
+}
+.mdui-tab a[disabled] {
+  cursor: default;
+  opacity: 0.38;
+}
+.mdui-tab a[disabled] label {
+  cursor: default;
+}
+.mdui-tab .mdui-tab-active {
+  color: #3F51B5;
+  opacity: 1;
+}
+.mdui-tab .mdui-tab-active .mdui-icon {
+  opacity: 1;
+}
+/* 选项卡居中 */
+@media (min-width: 600px) {
+  .mdui-tab-centered::before {
+    -webkit-box-flex: 1;
+        -ms-flex-positive: 1;
+            flex-grow: 1;
+    content: ' ';
+  }
+  .mdui-tab-centered::after {
+    -webkit-box-flex: 1;
+        -ms-flex-positive: 1;
+            flex-grow: 1;
+    content: ' ';
+  }
+  .mdui-tab-centered a {
+    -webkit-box-flex: 0;
+        -ms-flex: none;
+            flex: none;
+  }
+}
+/* 选项卡始终全宽等分 */
+.mdui-tab-full-width a {
+  -webkit-box-flex: 1;
+      -ms-flex: 1;
+          flex: 1;
+  max-width: none;
+}
+/* 可横向滚动的选项卡 */
+.mdui-tab-scrollable {
+  padding-left: 56px;
+}
+.mdui-tab-scrollable a {
+  -webkit-box-flex: 0;
+      -ms-flex: none;
+          flex: none;
+}
+@media (max-width: 599.9px) {
+  .mdui-tab-scrollable {
+    padding-left: 60px;
+  }
+}
+/* 下划线指示器 */
+.mdui-tab-indicator {
+  position: absolute;
+  bottom: 0;
+  height: 2px;
+  background-color: #3F51B5;
+  -webkit-transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: left, width;
+}
+/**
+ * =============================================================================
+ * ************   Tab 主色   ************
+ * =============================================================================
+ */
+.mdui-theme-primary-amber .mdui-tab .mdui-tab-active {
+  color: #FFC107;
+}
+.mdui-theme-primary-amber .mdui-tab-indicator {
+  background-color: #FFC107;
+}
+.mdui-theme-primary-blue .mdui-tab .mdui-tab-active {
+  color: #2196F3;
+}
+.mdui-theme-primary-blue .mdui-tab-indicator {
+  background-color: #2196F3;
+}
+.mdui-theme-primary-blue-grey .mdui-tab .mdui-tab-active {
+  color: #607D8B;
+}
+.mdui-theme-primary-blue-grey .mdui-tab-indicator {
+  background-color: #607D8B;
+}
+.mdui-theme-primary-brown .mdui-tab .mdui-tab-active {
+  color: #795548;
+}
+.mdui-theme-primary-brown .mdui-tab-indicator {
+  background-color: #795548;
+}
+.mdui-theme-primary-cyan .mdui-tab .mdui-tab-active {
+  color: #00BCD4;
+}
+.mdui-theme-primary-cyan .mdui-tab-indicator {
+  background-color: #00BCD4;
+}
+.mdui-theme-primary-deep-orange .mdui-tab .mdui-tab-active {
+  color: #FF5722;
+}
+.mdui-theme-primary-deep-orange .mdui-tab-indicator {
+  background-color: #FF5722;
+}
+.mdui-theme-primary-deep-purple .mdui-tab .mdui-tab-active {
+  color: #673AB7;
+}
+.mdui-theme-primary-deep-purple .mdui-tab-indicator {
+  background-color: #673AB7;
+}
+.mdui-theme-primary-green .mdui-tab .mdui-tab-active {
+  color: #4CAF50;
+}
+.mdui-theme-primary-green .mdui-tab-indicator {
+  background-color: #4CAF50;
+}
+.mdui-theme-primary-grey .mdui-tab .mdui-tab-active {
+  color: #9E9E9E;
+}
+.mdui-theme-primary-grey .mdui-tab-indicator {
+  background-color: #9E9E9E;
+}
+.mdui-theme-primary-indigo .mdui-tab .mdui-tab-active {
+  color: #3F51B5;
+}
+.mdui-theme-primary-indigo .mdui-tab-indicator {
+  background-color: #3F51B5;
+}
+.mdui-theme-primary-light-blue .mdui-tab .mdui-tab-active {
+  color: #03A9F4;
+}
+.mdui-theme-primary-light-blue .mdui-tab-indicator {
+  background-color: #03A9F4;
+}
+.mdui-theme-primary-light-green .mdui-tab .mdui-tab-active {
+  color: #8BC34A;
+}
+.mdui-theme-primary-light-green .mdui-tab-indicator {
+  background-color: #8BC34A;
+}
+.mdui-theme-primary-lime .mdui-tab .mdui-tab-active {
+  color: #CDDC39;
+}
+.mdui-theme-primary-lime .mdui-tab-indicator {
+  background-color: #CDDC39;
+}
+.mdui-theme-primary-orange .mdui-tab .mdui-tab-active {
+  color: #FF9800;
+}
+.mdui-theme-primary-orange .mdui-tab-indicator {
+  background-color: #FF9800;
+}
+.mdui-theme-primary-pink .mdui-tab .mdui-tab-active {
+  color: #E91E63;
+}
+.mdui-theme-primary-pink .mdui-tab-indicator {
+  background-color: #E91E63;
+}
+.mdui-theme-primary-purple .mdui-tab .mdui-tab-active {
+  color: #9C27B0;
+}
+.mdui-theme-primary-purple .mdui-tab-indicator {
+  background-color: #9C27B0;
+}
+.mdui-theme-primary-red .mdui-tab .mdui-tab-active {
+  color: #F44336;
+}
+.mdui-theme-primary-red .mdui-tab-indicator {
+  background-color: #F44336;
+}
+.mdui-theme-primary-teal .mdui-tab .mdui-tab-active {
+  color: #009688;
+}
+.mdui-theme-primary-teal .mdui-tab-indicator {
+  background-color: #009688;
+}
+.mdui-theme-primary-yellow .mdui-tab .mdui-tab-active {
+  color: #FFEB3B;
+}
+.mdui-theme-primary-yellow .mdui-tab-indicator {
+  background-color: #FFEB3B;
+}
+/* 带背景色的选项卡 */
+.mdui-tab[class*="mdui-color-"]:not(.mdui-color-white) .mdui-tab-active {
+  color: inherit;
+}
+.mdui-tab[class*="mdui-color-"]:not(.mdui-color-white) .mdui-tab-indicator {
+  background-color: #FFFFFF;
+}
+.mdui-tab[class*="mdui-color-"]:not(.mdui-color-white)::-webkit-scrollbar {
+  width: 5px;
+  height: 5px;
+  background: transparent;
+}
+@media (min-width: 1024px) {
+  .mdui-tab[class*="mdui-color-"]:not(.mdui-color-white)::-webkit-scrollbar {
+    width: 8px;
+    height: 8px;
+  }
+}
+.mdui-tab[class*="mdui-color-"]:not(.mdui-color-white)::-webkit-scrollbar-thumb {
+  background: rgba(255, 255, 255, 0.3);
+}
+/**
+ * =============================================================================
+ * ************   Subheader 副标题   ************
+ * =============================================================================
+ *
+ * 用于 List 和 Grid list 组件
+ */
+.mdui-subheader,
+.mdui-subheader-inset {
+  position: relative;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  height: 48px;
+  padding-right: 16px;
+  padding-left: 16px;
+  color: rgba(0, 0, 0, 0.54);
+  font-weight: 500;
+  font-size: 14px;
+  line-height: 48px;
+  cursor: default;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-subheader-inset {
+  padding-left: 72px;
+}
+/**
+ * =============================================================================
+ * ************   Subheader dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-subheader,
+.mdui-theme-layout-dark .mdui-subheader-inset {
+  color: rgba(255, 255, 255, 0.7);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-subheader,
+  .mdui-theme-layout-auto .mdui-subheader-inset {
+    color: rgba(255, 255, 255, 0.7);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Grid List 网格列表   ************
+ * =============================================================================
+ */
+/* 调整网格边距 */
+.mdui-grid-list {
+  margin: 0 -2px;
+}
+.mdui-grid-list .mdui-col,
+.mdui-grid-list [class*="mdui-col-xs-"],
+.mdui-grid-list [class*="mdui-col-sm-"],
+.mdui-grid-list [class*="mdui-col-md-"],
+.mdui-grid-list [class*="mdui-col-lg-"],
+.mdui-grid-list [class*="mdui-col-xl-"] {
+  padding-right: 2px;
+  padding-left: 2px;
+}
+/* 单元格 */
+.mdui-grid-tile {
+  position: relative;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  margin-bottom: 4px;
+  overflow: hidden;
+}
+.mdui-grid-tile img {
+  display: block;
+  width: 100%;
+}
+/* 操作栏 */
+.mdui-grid-tile-actions {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-align: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  min-height: 48px;
+  max-height: 68px;
+  padding: 16px;
+  color: #fff;
+  background: rgba(0, 0, 0, 0.2);
+}
+.mdui-grid-tile-actions .mdui-icon {
+  color: #fff;
+}
+/* 操作栏内的文本 */
+.mdui-grid-tile-text {
+  -webkit-box-flex: 1;
+      -ms-flex: 1;
+          flex: 1;
+  overflow: hidden;
+}
+/* 标题 */
+.mdui-grid-tile-title {
+  height: 16px;
+  font-size: 16px;
+  line-height: 16px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-grid-tile-title .mdui-icon {
+  margin-right: 8px;
+}
+/* 副标题 */
+.mdui-grid-tile-subtitle {
+  height: 18px;
+  margin-top: 4px;
+  font-size: 12px;
+  line-height: 18px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-grid-tile-subtitle .mdui-icon {
+  margin-right: 8px;
+  font-size: 18px;
+}
+/* 操作栏内的按钮 */
+.mdui-grid-tile-buttons {
+  -webkit-box-flex: 0;
+      -ms-flex: none;
+          flex: none;
+  margin: -8px;
+  white-space: nowrap;
+}
+.mdui-grid-tile-buttons .mdui-btn {
+  margin-left: 8px;
+}
+.mdui-grid-tile-buttons .mdui-btn:first-child {
+  margin-left: 0;
+}
+.mdui-grid-tile-text + .mdui-grid-tile-buttons {
+  margin-left: 8px;
+}
+.mdui-grid-tile-buttons + .mdui-grid-tile-text {
+  margin-left: 16px;
+}
+/* 操作栏位于顶部 */
+.mdui-grid-tile-actions-top {
+  top: 0;
+  bottom: auto;
+}
+/* 操作栏背景透明 */
+.mdui-grid-tile-actions-transparent {
+  background: transparent;
+}
+/* 操作栏背景渐变 */
+.mdui-grid-tile-actions-gradient {
+  background: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.26)), to(rgba(0, 0, 0, 0)));
+  background: linear-gradient(to top, rgba(0, 0, 0, 0.26), rgba(0, 0, 0, 0));
+}
+.mdui-grid-tile-actions-gradient.mdui-grid-tile-actions-top {
+  background: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.26)), to(rgba(0, 0, 0, 0)));
+  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.26), rgba(0, 0, 0, 0));
+}
+/**
+ * =============================================================================
+ * ************   List 列表   ************
+ * =============================================================================
+ */
+/* 列表 */
+.mdui-list {
+  margin: 0;
+  padding: 8px 0;
+  list-style: none;
+  background-color: transparent;
+}
+.mdui-list .mdui-list {
+  padding: 0;
+}
+.mdui-list > .mdui-divider,
+.mdui-list > .mdui-divider-light,
+.mdui-list > .mdui-divider-dark,
+.mdui-list > .mdui-divider-inset,
+.mdui-list > .mdui-divider-inset-light,
+.mdui-list > .mdui-divider-inset-dark {
+  margin-top: 8px;
+  margin-bottom: 8px;
+}
+.mdui-list a {
+  color: inherit;
+  text-decoration: none;
+}
+.mdui-list .mdui-subheader,
+.mdui-list .mdui-subheader-inset {
+  margin-top: 8px;
+}
+.mdui-list .mdui-subheader::before,
+.mdui-list .mdui-subheader-inset::before {
+  position: absolute;
+  right: 0;
+  left: 0;
+  display: block;
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.12);
+  content: ' ';
+}
+.mdui-list .mdui-subheader:first-child,
+.mdui-list .mdui-subheader-inset:first-child {
+  margin-top: -8px;
+}
+.mdui-list .mdui-subheader:first-child::before,
+.mdui-list .mdui-subheader-inset:first-child::before {
+  background-color: transparent;
+}
+.mdui-list .mdui-subheader-inset::before {
+  left: 72px;
+}
+/* 列表项 */
+.mdui-list-item {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-align: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  min-height: 48px;
+  padding: 0 16px;
+  text-decoration: none;
+  cursor: pointer;
+  -webkit-transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+.mdui-list-item:hover {
+  background-color: rgba(0, 0, 0, 0.08);
+}
+.mdui-list-item::after {
+  height: 48px;
+  visibility: hidden;
+  content: ' ';
+}
+/* 列表项图标 */
+.mdui-list-item-icon {
+  width: 24px;
+  min-width: 24px;
+  height: 24px;
+  color: rgba(0, 0, 0, 0.54);
+}
+/* 列表项头像 */
+.mdui-list-item-avatar {
+  min-width: 40px;
+  max-width: 40px;
+  height: 40px;
+  margin-top: 8px;
+  margin-bottom: 8px;
+  color: #FFFFFF;
+  line-height: 40px;
+  text-align: center;
+  background-color: #BDBDBD;
+  border-radius: 50%;
+}
+.mdui-list-item-avatar img {
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+}
+/* 列表项内容 */
+.mdui-list-item-content {
+  -webkit-box-flex: 1;
+      -ms-flex-positive: 1;
+          flex-grow: 1;
+  padding-top: 14px;
+  padding-bottom: 14px;
+  font-weight: 400;
+  font-size: 16px;
+  line-height: 20px;
+}
+/* 列表项内容的副内容 */
+.mdui-list-item-text {
+  font-size: 14px;
+  opacity: 0.54;
+}
+.mdui-list-item-title ~ .mdui-list-item-text {
+  margin-top: 4px;
+}
+/* 激活状态的列表项 */
+.mdui-list-item-active {
+  font-weight: 700;
+  background-color: rgba(0, 0, 0, 0.08);
+}
+.mdui-list-item-active .mdui-list-item-content {
+  font-weight: 700;
+}
+.mdui-list-item-active .mdui-list-item-text {
+  font-weight: 400;
+}
+/* 限制文本高度 */
+.mdui-list-item-one-line,
+.mdui-list-item-two-line,
+.mdui-list-item-three-line {
+  display: -webkit-box;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-box-orient: vertical;
+}
+.mdui-list-item-one-line {
+  -webkit-line-clamp: 1;
+  height: 20px;
+}
+.mdui-list-item-two-line {
+  -webkit-line-clamp: 2;
+  height: 40px;
+}
+.mdui-list-item-three-line {
+  -webkit-line-clamp: 3;
+  height: 60px;
+}
+/* 列表项内的元素间添加间距 */
+.mdui-list-item-icon ~ .mdui-list-item-content {
+  margin-left: 32px;
+}
+.mdui-checkbox ~ .mdui-list-item-content,
+.mdui-radio ~ .mdui-list-item-content,
+.mdui-switch ~ .mdui-list-item-content {
+  margin-left: 20px;
+}
+.mdui-list-item-avatar ~ .mdui-list-item-content {
+  margin-left: 16px;
+}
+.mdui-list-item-content ~ .mdui-list-item-icon,
+.mdui-list-item-content ~ .mdui-list-item-avatar,
+.mdui-list-item-content ~ .mdui-checkbox,
+.mdui-list-item-content ~ .mdui-radio,
+.mdui-list-item-content ~ .mdui-switch {
+  margin-left: 16px;
+}
+.mdui-list-item-content ~ .mdui-checkbox,
+.mdui-list-item-content ~ .mdui-radio {
+  padding-left: 24px;
+}
+/* 密集型列表 */
+.mdui-list-dense {
+  padding: 4px 0;
+  font-size: 13px;
+}
+.mdui-list-dense > .mdui-divider,
+.mdui-list-dense > .mdui-divider-light,
+.mdui-list-dense > .mdui-divider-dark,
+.mdui-list-dense > .mdui-divider-inset,
+.mdui-list-dense > .mdui-divider-inset-light,
+.mdui-list-dense > .mdui-divider-inset-dark {
+  margin-top: 4px;
+  margin-bottom: 4px;
+}
+.mdui-list-dense .mdui-subheader,
+.mdui-list-dense .mdui-subheader-inset {
+  height: 40px;
+  margin-top: 4px;
+  font-size: 12px;
+  line-height: 40px;
+}
+.mdui-list-dense .mdui-subheader:first-child,
+.mdui-list-dense .mdui-subheader-inset:first-child {
+  margin-top: -4px;
+}
+.mdui-list-dense .mdui-list-item {
+  min-height: 40px;
+}
+.mdui-list-dense .mdui-list-item::after {
+  height: 40px;
+}
+.mdui-list-dense .mdui-list-item-icon {
+  width: 20px;
+  height: 20px;
+  font-size: 20px;
+}
+.mdui-list-dense .mdui-list-item-avatar {
+  width: 36px;
+  min-width: 36px;
+  height: 36px;
+  min-height: 36px;
+}
+.mdui-list-dense .mdui-list-item-content {
+  padding-top: 11px;
+  padding-bottom: 11px;
+  font-size: 13px;
+  line-height: 18px;
+}
+.mdui-list-dense .mdui-list-item-text {
+  font-size: 13px;
+}
+.mdui-list-dense .mdui-list-item-title ~ .mdui-list-item-text {
+  margin-top: 2px;
+}
+.mdui-list-dense .mdui-list-item-one-line {
+  height: 18px;
+}
+.mdui-list-dense .mdui-list-item-two-line {
+  height: 36px;
+}
+.mdui-list-dense .mdui-list-item-three-line {
+  height: 54px;
+}
+/**
+ * =============================================================================
+ * ************   List dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-list .mdui-subheader::before,
+.mdui-theme-layout-dark .mdui-list .mdui-subheader-inset::before {
+  background-color: rgba(255, 255, 255, 0.12);
+}
+.mdui-theme-layout-dark .mdui-list .mdui-subheader:first-child::before,
+.mdui-theme-layout-dark .mdui-list .mdui-subheader-inset:first-child::before {
+  background-color: transparent;
+}
+.mdui-theme-layout-dark .mdui-list-item {
+  color: #ffffff;
+}
+.mdui-theme-layout-dark .mdui-list-item:hover {
+  background-color: rgba(255, 255, 255, 0.08);
+}
+.mdui-theme-layout-dark .mdui-list-item-icon {
+  color: #ffffff;
+}
+.mdui-theme-layout-dark .mdui-list-item-text {
+  opacity: 0.7;
+}
+.mdui-theme-layout-dark .mdui-list-item-active {
+  background-color: rgba(255, 255, 255, 0.08);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-list .mdui-subheader::before,
+  .mdui-theme-layout-auto .mdui-list .mdui-subheader-inset::before {
+    background-color: rgba(255, 255, 255, 0.12);
+  }
+  .mdui-theme-layout-auto .mdui-list .mdui-subheader:first-child::before,
+  .mdui-theme-layout-auto .mdui-list .mdui-subheader-inset:first-child::before {
+    background-color: transparent;
+  }
+  .mdui-theme-layout-auto .mdui-list-item {
+    color: #ffffff;
+  }
+  .mdui-theme-layout-auto .mdui-list-item:hover {
+    background-color: rgba(255, 255, 255, 0.08);
+  }
+  .mdui-theme-layout-auto .mdui-list-item-icon {
+    color: #ffffff;
+  }
+  .mdui-theme-layout-auto .mdui-list-item-text {
+    opacity: 0.7;
+  }
+  .mdui-theme-layout-auto .mdui-list-item-active {
+    background-color: rgba(255, 255, 255, 0.08);
+  }
+}
+/**
+ * ==============================================================================
+ * ************   List inner theme   ************
+ * ==============================================================================
+ */
+[class*="mdui-color-"] .mdui-list-item {
+  color: inherit;
+}
+[class*="mdui-color-"] .mdui-list-item-icon {
+  color: inherit;
+}
+/**
+ * =============================================================================
+ * ************   Drawer 抽屉栏导航   ************
+ * =============================================================================
+ */
+/* DOM 加载完后再添加 transition */
+body.mdui-loaded {
+  -webkit-transition: padding 0.3s cubic-bezier(0, 0, 0.2, 1);
+  transition: padding 0.3s cubic-bezier(0, 0, 0.2, 1);
+}
+body.mdui-loaded .mdui-drawer {
+  -webkit-transition: all 0.3s cubic-bezier(0, 0, 0.2, 1);
+  transition: all 0.3s cubic-bezier(0, 0, 0.2, 1);
+}
+/* 抽屉栏外层,默认出现在左侧且隐藏 */
+.mdui-drawer {
+  position: fixed;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 5000;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  /* stylelint-disable-next-line */
+  width: calc(100% - 56px);
+  max-width: 280px;
+  margin: 0;
+  overflow-x: hidden;
+  overflow-y: auto;
+  white-space: nowrap;
+  will-change: transform;
+  -webkit-overflow-scrolling: touch;
+}
+@media (max-width: 1023.9px) {
+  .mdui-drawer:not(.mdui-drawer-open) {
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+}
+@media (min-width: 600px) {
+  .mdui-drawer {
+    /* stylelint-disable-next-line */
+    width: calc(100% - 64px);
+    max-width: 320px;
+  }
+}
+@media (min-width: 1024px) {
+  .mdui-drawer {
+    width: 240px;
+    max-width: none;
+  }
+  .mdui-drawer.mdui-drawer-close {
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+}
+/* 出现在右侧的抽屉栏 */
+.mdui-drawer-right {
+  right: 0;
+  left: auto;
+}
+/* 平板上的样式 */
+@media (max-width: 1023.9px) {
+  .mdui-drawer {
+    /* 始终有背景和阴影 */
+    background-color: #fff;
+    /* 默认隐藏 */
+    -webkit-transform: translateX(-330px);
+            transform: translateX(-330px);
+    -webkit-box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12);
+            box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12);
+  }
+  .mdui-drawer-right {
+    /* 右侧 drawer 也默认隐藏 */
+    -webkit-transform: translateX(330px);
+            transform: translateX(330px);
+  }
+}
+/* 手机上的样式 */
+@media (max-width: 599.9px) {
+  .mdui-drawer {
+    -webkit-transform: translateX(-290px);
+            transform: translateX(-290px);
+  }
+  .mdui-drawer-right {
+    -webkit-transform: translateX(290px);
+            transform: translateX(290px);
+  }
+}
+/* 强制隐藏抽屉栏 */
+.mdui-drawer-close {
+  -webkit-transform: translateX(-290px);
+          transform: translateX(-290px);
+}
+.mdui-drawer-close.mdui-drawer-right {
+  -webkit-transform: translateX(290px);
+          transform: translateX(290px);
+}
+@media (min-width: 600px) {
+  .mdui-drawer-close {
+    -webkit-transform: translateX(-330px);
+            transform: translateX(-330px);
+  }
+  .mdui-drawer-close.mdui-drawer-right {
+    -webkit-transform: translateX(330px);
+            transform: translateX(330px);
+  }
+}
+@media (min-width: 1024px) {
+  .mdui-drawer-close {
+    -webkit-transform: translateX(-250px);
+            transform: translateX(-250px);
+  }
+  .mdui-drawer-close.mdui-drawer-right {
+    -webkit-transform: translateX(250px);
+            transform: translateX(250px);
+  }
+}
+/* 强制显示抽屉栏 */
+.mdui-drawer-open {
+  -webkit-transform: translateX(0) !important;
+          transform: translateX(0) !important;
+}
+/* PC 上的样式 */
+@media (min-width: 1024px) {
+  /* 使该类所在元素获得 padding-left 或 padding-right,避免被抽屉栏覆盖住页面 */
+  .mdui-drawer-body-left {
+    padding-left: 240px;
+  }
+  .mdui-drawer-body-right {
+    padding-right: 240px;
+  }
+  /* PC 上默认有上边距 */
+  .mdui-appbar-with-toolbar .mdui-drawer {
+    top: 64px;
+  }
+  .mdui-appbar-with-tab .mdui-drawer {
+    top: 48px;
+  }
+  .mdui-appbar-with-tab-larger .mdui-drawer {
+    top: 72px;
+  }
+  .mdui-appbar-with-toolbar.mdui-appbar-with-tab .mdui-drawer {
+    top: 112px;
+  }
+  .mdui-appbar-with-toolbar.mdui-appbar-with-tab-larger .mdui-drawer {
+    top: 136px;
+  }
+}
+/* 抽屉栏不是透明时添加阴影 */
+.mdui-drawer[class*="mdui-color-"]:not(.mdui-color-transparent) {
+  -webkit-box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12);
+}
+/* 抽屉栏 100% 高度,覆盖在导航栏上面 */
+.mdui-drawer-full-height {
+  top: 0 !important;
+}
+/**
+ * =============================================================================
+ * ************   Drawer dark   ************
+ * =============================================================================
+ */
+@media (max-width: 1023.9px) {
+  .mdui-theme-layout-dark .mdui-drawer {
+    background-color: #424242;
+  }
+}
+@media (prefers-color-scheme: dark) and (max-width: 1023.9px) {
+  .mdui-theme-layout-auto .mdui-drawer {
+    background-color: #424242;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Dialog 提示框   ************
+ * =============================================================================
+ */
+.mdui-dialog {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 6000;
+  display: none;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 92%;
+  min-width: 180px;
+  max-width: 728px;
+  max-height: 90%;
+  margin: auto;
+  overflow: hidden;
+  color: #000;
+  background-color: #fff;
+  border-radius: 2px;
+  -webkit-transform: scale(0.95);
+          transform: scale(0.95);
+  opacity: 0;
+  -webkit-transition-duration: 0.3s;
+          transition-duration: 0.3s;
+  -webkit-transition-property: opacity, visibility, -webkit-transform;
+  transition-property: opacity, visibility, -webkit-transform;
+  transition-property: transform, opacity, visibility;
+  transition-property: transform, opacity, visibility, -webkit-transform;
+  will-change: top, opacity, transform;
+  -webkit-box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2), 0 24px 38px 3px rgba(0, 0, 0, 0.14), 0 9px 46px 8px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2), 0 24px 38px 3px rgba(0, 0, 0, 0.14), 0 9px 46px 8px rgba(0, 0, 0, 0.12);
+}
+@media (min-width: 600px) {
+  .mdui-dialog {
+    width: 85%;
+    max-height: 85%;
+  }
+}
+@media (min-width: 1024px) {
+  .mdui-dialog {
+    width: 80%;
+    max-height: 80%;
+  }
+}
+/* 打开提示框 */
+.mdui-dialog-open {
+  -webkit-transform: scale(1);
+          transform: scale(1);
+  opacity: 1;
+}
+/* 提示框标题 */
+.mdui-dialog-title {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  font-weight: 500;
+  font-size: 20px;
+  line-height: 24px;
+  text-align: left;
+}
+/* 标题固定在顶部 */
+.mdui-dialog > .mdui-dialog-title {
+  padding: 24px 24px 20px 24px;
+}
+/* 提示框内容 */
+.mdui-dialog-content {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 24px;
+  overflow-y: auto;
+  color: rgba(0, 0, 0, 0.7);
+  font-size: 15px;
+  line-height: 1.5;
+  -webkit-overflow-scrolling: touch;
+}
+/* 标题随内容滚动 */
+.mdui-dialog-content > .mdui-dialog-title {
+  padding-bottom: 20px;
+}
+.mdui-dialog-title + .mdui-dialog-content {
+  padding-top: 0;
+}
+/* 提示框底部按钮 */
+.mdui-dialog-actions {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 8px;
+  text-align: right;
+}
+.mdui-dialog-actions .mdui-btn {
+  min-width: 64px;
+  margin-left: 8px;
+  color: #E91E63;
+}
+.mdui-dialog-actions .mdui-btn:first-child {
+  margin-left: 0;
+}
+/* 底部按钮滚随内容动 */
+.mdui-dialog-content > .mdui-dialog-actions {
+  margin: 0 -24px -24px -24px;
+  padding-top: 32px;
+}
+/* 使提示框底部按钮竖排 */
+.mdui-dialog-actions-stacked {
+  padding: 8px 0 8px 0;
+}
+.mdui-dialog-actions-stacked .mdui-btn {
+  width: 100%;
+  height: 48px;
+  margin: 0;
+  line-height: 48px !important;
+  text-align: right;
+  border-radius: 0;
+}
+/**
+ * =============================================================================
+ * ************   Dialog 强调色   ************
+ * =============================================================================
+ */
+.mdui-theme-accent-amber .mdui-dialog-actions .mdui-btn {
+  color: #FFC107;
+}
+.mdui-theme-accent-blue .mdui-dialog-actions .mdui-btn {
+  color: #2196F3;
+}
+.mdui-theme-accent-cyan .mdui-dialog-actions .mdui-btn {
+  color: #00BCD4;
+}
+.mdui-theme-accent-deep-orange .mdui-dialog-actions .mdui-btn {
+  color: #FF5722;
+}
+.mdui-theme-accent-deep-purple .mdui-dialog-actions .mdui-btn {
+  color: #673AB7;
+}
+.mdui-theme-accent-green .mdui-dialog-actions .mdui-btn {
+  color: #4CAF50;
+}
+.mdui-theme-accent-indigo .mdui-dialog-actions .mdui-btn {
+  color: #3F51B5;
+}
+.mdui-theme-accent-light-blue .mdui-dialog-actions .mdui-btn {
+  color: #03A9F4;
+}
+.mdui-theme-accent-light-green .mdui-dialog-actions .mdui-btn {
+  color: #8BC34A;
+}
+.mdui-theme-accent-lime .mdui-dialog-actions .mdui-btn {
+  color: #CDDC39;
+}
+.mdui-theme-accent-orange .mdui-dialog-actions .mdui-btn {
+  color: #FF9800;
+}
+.mdui-theme-accent-pink .mdui-dialog-actions .mdui-btn {
+  color: #E91E63;
+}
+.mdui-theme-accent-purple .mdui-dialog-actions .mdui-btn {
+  color: #9C27B0;
+}
+.mdui-theme-accent-red .mdui-dialog-actions .mdui-btn {
+  color: #F44336;
+}
+.mdui-theme-accent-teal .mdui-dialog-actions .mdui-btn {
+  color: #009688;
+}
+.mdui-theme-accent-yellow .mdui-dialog-actions .mdui-btn {
+  color: #FFEB3B;
+}
+/**
+ * =============================================================================
+ * ************   Dialog dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-dialog {
+  color: #fff;
+  background-color: #424242;
+}
+.mdui-theme-layout-dark .mdui-dialog-content {
+  color: rgba(255, 255, 255, 0.7);
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-dialog {
+    color: #fff;
+    background-color: #424242;
+  }
+  .mdui-theme-layout-auto .mdui-dialog-content {
+    color: rgba(255, 255, 255, 0.7);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Dialog alert   ************
+ * =============================================================================
+ */
+.mdui-dialog-alert {
+  max-width: 448px;
+}
+/**
+ * =============================================================================
+ * ************   Dialog confirm   ************
+ * =============================================================================
+ */
+.mdui-dialog-confirm {
+  max-width: 448px;
+}
+/**
+ * =============================================================================
+ * ************   Dialog prompt   ************
+ * =============================================================================
+ */
+.mdui-dialog-prompt {
+  max-width: 448px;
+}
+.mdui-dialog-prompt .mdui-textfield {
+  padding-top: 0;
+}
+/**
+ * =============================================================================
+ * ************   Tooltip 工具提示   ************
+ * =============================================================================
+ */
+.mdui-tooltip {
+  position: absolute;
+  z-index: 9000;
+  display: inline-block;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  max-width: 180px;
+  min-height: 32px;
+  padding: 8px 16px;
+  color: #fff;
+  font-weight: 500;
+  font-size: 14px;
+  line-height: 22px;
+  text-align: left;
+  background-color: rgba(97, 97, 97, 0.9);
+  border-radius: 2px;
+  -webkit-transform: scale(0);
+          transform: scale(0);
+  opacity: 0;
+  -webkit-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+          transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+  -webkit-transition-duration: 0.15s;
+          transition-duration: 0.15s;
+  -webkit-transition-property: opacity, -webkit-transform;
+  transition-property: opacity, -webkit-transform;
+  transition-property: opacity, transform;
+  transition-property: opacity, transform, -webkit-transform;
+  will-change: opacity, transform;
+}
+@media (min-width: 1024px) {
+  .mdui-tooltip {
+    max-width: 200px;
+    min-height: 24px;
+    padding: 4px 8px;
+    font-size: 12px;
+    line-height: 18px;
+  }
+}
+/* 显示工具提示 */
+.mdui-tooltip-open {
+  -webkit-transform: scale(1);
+          transform: scale(1);
+  opacity: 1;
+}
+/**
+ * =============================================================================
+ * ************   Snackbar   ************
+ * =============================================================================
+ */
+.mdui-snackbar {
+  position: fixed;
+  z-index: 7000;
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-align: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-pack: justify;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 100%;
+  min-height: 48px;
+  padding: 0 24px 0 24px;
+  color: #fff;
+  font-size: 14px;
+  line-height: 20px;
+  background-color: #323232;
+  will-change: transform;
+}
+@media (min-width: 600px) {
+  .mdui-snackbar {
+    width: auto;
+    min-width: 288px;
+    max-width: 568px;
+    border-radius: 2px;
+  }
+}
+.mdui-snackbar-bottom,
+.mdui-snackbar-top,
+.mdui-snackbar-left-top,
+.mdui-snackbar-left-bottom,
+.mdui-snackbar-right-top,
+.mdui-snackbar-right-bottom {
+  -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: -webkit-transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), -webkit-transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+/* 位置 */
+.mdui-snackbar-bottom,
+.mdui-snackbar-left-bottom,
+.mdui-snackbar-right-bottom {
+  bottom: 0;
+}
+.mdui-snackbar-top,
+.mdui-snackbar-left-top,
+.mdui-snackbar-right-top {
+  top: 0;
+}
+.mdui-snackbar-top,
+.mdui-snackbar-bottom {
+  left: 50%;
+}
+@media (min-width: 600px) {
+  .mdui-snackbar-left-top {
+    top: 24px;
+    left: 24px;
+  }
+  .mdui-snackbar-left-bottom {
+    bottom: 24px;
+    left: 24px;
+  }
+  .mdui-snackbar-right-top {
+    top: 24px;
+    right: 24px;
+  }
+  .mdui-snackbar-right-bottom {
+    right: 24px;
+    bottom: 24px;
+  }
+}
+/* 文本 */
+.mdui-snackbar-text {
+  position: relative;
+  max-width: 100%;
+  padding: 14px 0 14px 0;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+/* 按钮 */
+.mdui-snackbar-action {
+  margin-right: -16px;
+  white-space: nowrap;
+  color: #FF80AB;
+}
+/**
+ * =============================================================================
+ * ************   Snackbar 强调色   ************
+ * =============================================================================
+ */
+.mdui-theme-accent-amber .mdui-snackbar-action {
+  color: #FFE57F;
+}
+.mdui-theme-accent-blue .mdui-snackbar-action {
+  color: #82B1FF;
+}
+.mdui-theme-accent-cyan .mdui-snackbar-action {
+  color: #84FFFF;
+}
+.mdui-theme-accent-deep-orange .mdui-snackbar-action {
+  color: #FF9E80;
+}
+.mdui-theme-accent-deep-purple .mdui-snackbar-action {
+  color: #B388FF;
+}
+.mdui-theme-accent-green .mdui-snackbar-action {
+  color: #B9F6CA;
+}
+.mdui-theme-accent-indigo .mdui-snackbar-action {
+  color: #8C9EFF;
+}
+.mdui-theme-accent-light-blue .mdui-snackbar-action {
+  color: #80D8FF;
+}
+.mdui-theme-accent-light-green .mdui-snackbar-action {
+  color: #CCFF90;
+}
+.mdui-theme-accent-lime .mdui-snackbar-action {
+  color: #F4FF81;
+}
+.mdui-theme-accent-orange .mdui-snackbar-action {
+  color: #FFD180;
+}
+.mdui-theme-accent-pink .mdui-snackbar-action {
+  color: #FF80AB;
+}
+.mdui-theme-accent-purple .mdui-snackbar-action {
+  color: #EA80FC;
+}
+.mdui-theme-accent-red .mdui-snackbar-action {
+  color: #FF8A80;
+}
+.mdui-theme-accent-teal .mdui-snackbar-action {
+  color: #A7FFEB;
+}
+.mdui-theme-accent-yellow .mdui-snackbar-action {
+  color: #FFFF8D;
+}
+/**
+ * =============================================================================
+ * ************   Snackbar dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-snackbar {
+  background-color: #5d5d5d;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-snackbar {
+    background-color: #5d5d5d;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Chip 纸片   ************
+ * =============================================================================
+ */
+.mdui-chip {
+  display: inline-block;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  height: 32px;
+  margin: 2px 0;
+  color: inherit;
+  white-space: nowrap;
+  background-color: #e0e0e0;
+  border-radius: 16px;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-transition: -webkit-box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: -webkit-box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1), -webkit-box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: box-shadow;
+}
+.mdui-chip:hover,
+.mdui-chip:focus {
+  -webkit-box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+          box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+}
+.mdui-chip:active {
+  background-color: #d6d6d6;
+}
+/* 左侧的图标 */
+.mdui-chip-icon {
+  position: relative;
+  display: inline-block;
+  width: 32px;
+  height: 32px;
+  margin-right: -4px;
+  overflow: hidden;
+  color: #fff;
+  font-size: 18px;
+  line-height: 32px;
+  text-align: center;
+  vertical-align: middle;
+  background-color: #989898;
+  border-radius: 50%;
+}
+.mdui-chip-icon .mdui-icon {
+  position: absolute;
+  top: 4px;
+  left: 4px;
+  color: #fff;
+}
+/* 文本 */
+.mdui-chip-title {
+  display: inline-block;
+  height: 32px;
+  padding-right: 12px;
+  padding-left: 12px;
+  font-size: 14px;
+  line-height: 32px;
+  vertical-align: middle;
+}
+/* 删除按钮 */
+.mdui-chip-delete {
+  display: inline-block;
+  width: 24px;
+  height: 24px;
+  margin-right: 4px;
+  margin-left: -8px;
+  overflow: hidden;
+  text-align: center;
+  text-decoration: none;
+  vertical-align: middle;
+  border-radius: 50%;
+  cursor: pointer;
+  opacity: 0.54;
+  -webkit-transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: opacity;
+}
+.mdui-chip-delete:hover,
+.mdui-chip-delete:focus {
+  opacity: 0.87;
+}
+/**
+ * =============================================================================
+ * ************   Chip dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-chip {
+  background-color: #484848;
+}
+.mdui-theme-layout-dark .mdui-chip:active {
+  background-color: #5d5d5d;
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-chip {
+    background-color: #484848;
+  }
+  .mdui-theme-layout-auto .mdui-chip:active {
+    background-color: #5d5d5d;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Bottom navigation 底部导航栏   ************
+ * =============================================================================
+ */
+.mdui-bottom-nav {
+  position: relative;
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  height: 56px;
+  margin: 0 auto;
+  padding: 0;
+  overflow: hidden;
+  white-space: nowrap;
+}
+@media (min-width: 600px) {
+  .mdui-bottom-nav::before {
+    -webkit-box-flex: 1;
+        -ms-flex-positive: 1;
+            flex-grow: 1;
+    content: ' ';
+  }
+  .mdui-bottom-nav::after {
+    -webkit-box-flex: 1;
+        -ms-flex-positive: 1;
+            flex-grow: 1;
+    content: ' ';
+  }
+}
+.mdui-bottom-nav a {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-flex: 1;
+      -ms-flex: 1;
+          flex: 1;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+      -ms-flex-direction: column;
+          flex-direction: column;
+  -webkit-box-align: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-pack: center;
+      -ms-flex-pack: center;
+          justify-content: center;
+  min-width: 32px;
+  max-width: none;
+  padding: 8px 12px 10px 12px;
+  overflow: hidden;
+  color: inherit;
+  font-size: 12px;
+  text-align: center;
+  text-decoration: none;
+  text-overflow: ellipsis;
+  cursor: pointer;
+  opacity: 0.7;
+  -webkit-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  will-change: padding;
+}
+@media (min-width: 600px) {
+  .mdui-bottom-nav a {
+    max-width: 144px;
+  }
+}
+.mdui-bottom-nav a .mdui-icon {
+  opacity: 0.7;
+}
+.mdui-bottom-nav a label {
+  display: block;
+  width: 100%;
+  cursor: pointer;
+  -webkit-transition: -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: font-size;
+}
+.mdui-bottom-nav a .mdui-icon + label {
+  margin-top: 6px;
+}
+.mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #3F51B5;
+  font-size: 14px;
+  opacity: 1;
+}
+.mdui-bottom-nav a.mdui-bottom-nav-active .mdui-icon {
+  opacity: 1;
+}
+/* 只在激活时显示文本 */
+.mdui-bottom-nav-text-auto a {
+  min-width: 32px;
+  padding-right: 0;
+  padding-left: 0;
+}
+@media (min-width: 600px) {
+  .mdui-bottom-nav-text-auto a {
+    max-width: 156px;
+  }
+}
+.mdui-bottom-nav-text-auto a .mdui-icon {
+  padding-top: 16px;
+  -webkit-transition: padding-top 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  transition: padding-top 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  will-change: padding-top;
+}
+.mdui-bottom-nav-text-auto a label {
+  -webkit-transform: scale(0);
+          transform: scale(0);
+}
+.mdui-bottom-nav-text-auto a.mdui-bottom-nav-active {
+  padding-right: 18px;
+  padding-left: 18px;
+}
+.mdui-bottom-nav-text-auto a.mdui-bottom-nav-active .mdui-icon {
+  padding-top: 0;
+}
+.mdui-bottom-nav-text-auto a.mdui-bottom-nav-active label {
+  -webkit-transform: scale(1);
+          transform: scale(1);
+}
+/* 固定到页面底部 */
+.mdui-bottom-nav-fixed {
+  padding-bottom: 56px;
+}
+.mdui-bottom-nav-fixed .mdui-bottom-nav {
+  position: fixed;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}
+/**
+ * =============================================================================
+ * ************   Bottom Nav 主色   ************
+ * =============================================================================
+ */
+.mdui-theme-primary-amber .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #FFC107;
+}
+.mdui-theme-primary-blue .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #2196F3;
+}
+.mdui-theme-primary-blue-grey .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #607D8B;
+}
+.mdui-theme-primary-brown .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #795548;
+}
+.mdui-theme-primary-cyan .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #00BCD4;
+}
+.mdui-theme-primary-deep-orange .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #FF5722;
+}
+.mdui-theme-primary-deep-purple .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #673AB7;
+}
+.mdui-theme-primary-green .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #4CAF50;
+}
+.mdui-theme-primary-grey .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #9E9E9E;
+}
+.mdui-theme-primary-indigo .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #3F51B5;
+}
+.mdui-theme-primary-light-blue .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #03A9F4;
+}
+.mdui-theme-primary-light-green .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #8BC34A;
+}
+.mdui-theme-primary-lime .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #CDDC39;
+}
+.mdui-theme-primary-orange .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #FF9800;
+}
+.mdui-theme-primary-pink .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #E91E63;
+}
+.mdui-theme-primary-purple .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #9C27B0;
+}
+.mdui-theme-primary-red .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #F44336;
+}
+.mdui-theme-primary-teal .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #009688;
+}
+.mdui-theme-primary-yellow .mdui-bottom-nav a.mdui-bottom-nav-active {
+  color: #FFEB3B;
+}
+/* 带背景色的底部导航栏 */
+.mdui-bottom-nav[class*="mdui-color-"] .mdui-bottom-nav-active {
+  color: inherit !important;
+}
+/**
+ * =============================================================================
+ * ************   Progress Linear 线性进度条   ************
+ * =============================================================================
+ */
+/* 线性进度条 */
+.mdui-progress {
+  position: relative;
+  display: block;
+  width: 100%;
+  height: 4px;
+  overflow: hidden;
+  background-color: rgba(63, 81, 181, 0.2);
+  border-radius: 2px;
+}
+/* 确定进度的线性进度条 */
+.mdui-progress-determinate {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  background-color: #3F51B5;
+  -webkit-transition: width 0.3s linear;
+  transition: width 0.3s linear;
+}
+/* 不确定进度的线性进度条 */
+.mdui-progress-indeterminate {
+  background-color: #3F51B5;
+}
+.mdui-progress-indeterminate::before {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  background-color: inherit;
+  -webkit-animation: mdui-progress-indeterminate 2s linear infinite;
+          animation: mdui-progress-indeterminate 2s linear infinite;
+  content: ' ';
+  will-change: left, width;
+}
+.mdui-progress-indeterminate::after {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  background-color: inherit;
+  -webkit-animation: mdui-progress-indeterminate-short 2s linear infinite;
+          animation: mdui-progress-indeterminate-short 2s linear infinite;
+  content: ' ';
+  will-change: left, width;
+}
+@-webkit-keyframes mdui-progress-indeterminate {
+  0% {
+    left: 0;
+    width: 0;
+  }
+  50% {
+    left: 30%;
+    width: 70%;
+  }
+  75% {
+    left: 100%;
+    width: 0;
+  }
+}
+@keyframes mdui-progress-indeterminate {
+  0% {
+    left: 0;
+    width: 0;
+  }
+  50% {
+    left: 30%;
+    width: 70%;
+  }
+  75% {
+    left: 100%;
+    width: 0;
+  }
+}
+@-webkit-keyframes mdui-progress-indeterminate-short {
+  0% {
+    left: 0;
+    width: 0;
+  }
+  50% {
+    left: 0;
+    width: 0;
+  }
+  75% {
+    left: 0;
+    width: 25%;
+  }
+  100% {
+    left: 100%;
+    width: 0;
+  }
+}
+@keyframes mdui-progress-indeterminate-short {
+  0% {
+    left: 0;
+    width: 0;
+  }
+  50% {
+    left: 0;
+    width: 0;
+  }
+  75% {
+    left: 0;
+    width: 25%;
+  }
+  100% {
+    left: 100%;
+    width: 0;
+  }
+}
+/**
+ * =============================================================================
+ * ************   Progress linear 主色   ************
+ * =============================================================================
+ */
+.mdui-theme-primary-amber .mdui-progress {
+  background-color: rgba(255, 193, 7, 0.2);
+}
+.mdui-theme-primary-amber .mdui-progress-determinate,
+.mdui-theme-primary-amber .mdui-progress-indeterminate {
+  background-color: #FFC107;
+}
+.mdui-theme-primary-blue .mdui-progress {
+  background-color: rgba(33, 150, 243, 0.2);
+}
+.mdui-theme-primary-blue .mdui-progress-determinate,
+.mdui-theme-primary-blue .mdui-progress-indeterminate {
+  background-color: #2196F3;
+}
+.mdui-theme-primary-blue-grey .mdui-progress {
+  background-color: rgba(96, 125, 139, 0.2);
+}
+.mdui-theme-primary-blue-grey .mdui-progress-determinate,
+.mdui-theme-primary-blue-grey .mdui-progress-indeterminate {
+  background-color: #607D8B;
+}
+.mdui-theme-primary-brown .mdui-progress {
+  background-color: rgba(121, 85, 72, 0.2);
+}
+.mdui-theme-primary-brown .mdui-progress-determinate,
+.mdui-theme-primary-brown .mdui-progress-indeterminate {
+  background-color: #795548;
+}
+.mdui-theme-primary-cyan .mdui-progress {
+  background-color: rgba(0, 188, 212, 0.2);
+}
+.mdui-theme-primary-cyan .mdui-progress-determinate,
+.mdui-theme-primary-cyan .mdui-progress-indeterminate {
+  background-color: #00BCD4;
+}
+.mdui-theme-primary-deep-orange .mdui-progress {
+  background-color: rgba(255, 87, 34, 0.2);
+}
+.mdui-theme-primary-deep-orange .mdui-progress-determinate,
+.mdui-theme-primary-deep-orange .mdui-progress-indeterminate {
+  background-color: #FF5722;
+}
+.mdui-theme-primary-deep-purple .mdui-progress {
+  background-color: rgba(103, 58, 183, 0.2);
+}
+.mdui-theme-primary-deep-purple .mdui-progress-determinate,
+.mdui-theme-primary-deep-purple .mdui-progress-indeterminate {
+  background-color: #673AB7;
+}
+.mdui-theme-primary-green .mdui-progress {
+  background-color: rgba(76, 175, 80, 0.2);
+}
+.mdui-theme-primary-green .mdui-progress-determinate,
+.mdui-theme-primary-green .mdui-progress-indeterminate {
+  background-color: #4CAF50;
+}
+.mdui-theme-primary-grey .mdui-progress {
+  background-color: rgba(158, 158, 158, 0.2);
+}
+.mdui-theme-primary-grey .mdui-progress-determinate,
+.mdui-theme-primary-grey .mdui-progress-indeterminate {
+  background-color: #9E9E9E;
+}
+.mdui-theme-primary-indigo .mdui-progress {
+  background-color: rgba(63, 81, 181, 0.2);
+}
+.mdui-theme-primary-indigo .mdui-progress-determinate,
+.mdui-theme-primary-indigo .mdui-progress-indeterminate {
+  background-color: #3F51B5;
+}
+.mdui-theme-primary-light-blue .mdui-progress {
+  background-color: rgba(3, 169, 244, 0.2);
+}
+.mdui-theme-primary-light-blue .mdui-progress-determinate,
+.mdui-theme-primary-light-blue .mdui-progress-indeterminate {
+  background-color: #03A9F4;
+}
+.mdui-theme-primary-light-green .mdui-progress {
+  background-color: rgba(139, 195, 74, 0.2);
+}
+.mdui-theme-primary-light-green .mdui-progress-determinate,
+.mdui-theme-primary-light-green .mdui-progress-indeterminate {
+  background-color: #8BC34A;
+}
+.mdui-theme-primary-lime .mdui-progress {
+  background-color: rgba(205, 220, 57, 0.2);
+}
+.mdui-theme-primary-lime .mdui-progress-determinate,
+.mdui-theme-primary-lime .mdui-progress-indeterminate {
+  background-color: #CDDC39;
+}
+.mdui-theme-primary-orange .mdui-progress {
+  background-color: rgba(255, 152, 0, 0.2);
+}
+.mdui-theme-primary-orange .mdui-progress-determinate,
+.mdui-theme-primary-orange .mdui-progress-indeterminate {
+  background-color: #FF9800;
+}
+.mdui-theme-primary-pink .mdui-progress {
+  background-color: rgba(233, 30, 99, 0.2);
+}
+.mdui-theme-primary-pink .mdui-progress-determinate,
+.mdui-theme-primary-pink .mdui-progress-indeterminate {
+  background-color: #E91E63;
+}
+.mdui-theme-primary-purple .mdui-progress {
+  background-color: rgba(156, 39, 176, 0.2);
+}
+.mdui-theme-primary-purple .mdui-progress-determinate,
+.mdui-theme-primary-purple .mdui-progress-indeterminate {
+  background-color: #9C27B0;
+}
+.mdui-theme-primary-red .mdui-progress {
+  background-color: rgba(244, 67, 54, 0.2);
+}
+.mdui-theme-primary-red .mdui-progress-determinate,
+.mdui-theme-primary-red .mdui-progress-indeterminate {
+  background-color: #F44336;
+}
+.mdui-theme-primary-teal .mdui-progress {
+  background-color: rgba(0, 150, 136, 0.2);
+}
+.mdui-theme-primary-teal .mdui-progress-determinate,
+.mdui-theme-primary-teal .mdui-progress-indeterminate {
+  background-color: #009688;
+}
+.mdui-theme-primary-yellow .mdui-progress {
+  background-color: rgba(255, 235, 59, 0.2);
+}
+.mdui-theme-primary-yellow .mdui-progress-determinate,
+.mdui-theme-primary-yellow .mdui-progress-indeterminate {
+  background-color: #FFEB3B;
+}
+/**
+ * =============================================================================
+ * ************   Progress Circular 圆形进度条   ************
+ * =============================================================================
+ */
+.mdui-spinner {
+  position: relative;
+  display: inline-block;
+  width: 28px;
+  height: 28px;
+  -webkit-animation: mdui-spinner 1568ms linear infinite;
+          animation: mdui-spinner 1568ms linear infinite;
+}
+@-webkit-keyframes mdui-spinner {
+  to {
+    -webkit-transform: rotate(360deg);
+            transform: rotate(360deg);
+  }
+}
+@keyframes mdui-spinner {
+  to {
+    -webkit-transform: rotate(360deg);
+            transform: rotate(360deg);
+  }
+}
+.mdui-spinner-layer {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  border-color: #3F51B5;
+  opacity: 0;
+  opacity: 1;
+  -webkit-animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+          animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+.mdui-spinner-layer-1 {
+  border-color: #42A5F5 !important;
+  -webkit-animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdui-spinner-layer-1-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+          animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdui-spinner-layer-1-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+.mdui-spinner-layer-2 {
+  border-color: #F44336 !important;
+  -webkit-animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdui-spinner-layer-2-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+          animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdui-spinner-layer-2-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+.mdui-spinner-layer-3 {
+  border-color: #FDD835 !important;
+  -webkit-animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdui-spinner-layer-3-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+          animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdui-spinner-layer-3-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+.mdui-spinner-layer-4 {
+  border-color: #4CAF50 !important;
+  -webkit-animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdui-spinner-layer-4-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+          animation: mdui-spinner-layer-fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdui-spinner-layer-4-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+@-webkit-keyframes mdui-spinner-layer-fill-unfill-rotate {
+  12.5% {
+    -webkit-transform: rotate(135deg);
+            transform: rotate(135deg);
+  }
+  25% {
+    -webkit-transform: rotate(270deg);
+            transform: rotate(270deg);
+  }
+  37.5% {
+    -webkit-transform: rotate(405deg);
+            transform: rotate(405deg);
+  }
+  50% {
+    -webkit-transform: rotate(540deg);
+            transform: rotate(540deg);
+  }
+  62.5% {
+    -webkit-transform: rotate(675deg);
+            transform: rotate(675deg);
+  }
+  75% {
+    -webkit-transform: rotate(810deg);
+            transform: rotate(810deg);
+  }
+  87.5% {
+    -webkit-transform: rotate(945deg);
+            transform: rotate(945deg);
+  }
+  to {
+    -webkit-transform: rotate(1080deg);
+            transform: rotate(1080deg);
+  }
+}
+@keyframes mdui-spinner-layer-fill-unfill-rotate {
+  12.5% {
+    -webkit-transform: rotate(135deg);
+            transform: rotate(135deg);
+  }
+  25% {
+    -webkit-transform: rotate(270deg);
+            transform: rotate(270deg);
+  }
+  37.5% {
+    -webkit-transform: rotate(405deg);
+            transform: rotate(405deg);
+  }
+  50% {
+    -webkit-transform: rotate(540deg);
+            transform: rotate(540deg);
+  }
+  62.5% {
+    -webkit-transform: rotate(675deg);
+            transform: rotate(675deg);
+  }
+  75% {
+    -webkit-transform: rotate(810deg);
+            transform: rotate(810deg);
+  }
+  87.5% {
+    -webkit-transform: rotate(945deg);
+            transform: rotate(945deg);
+  }
+  to {
+    -webkit-transform: rotate(1080deg);
+            transform: rotate(1080deg);
+  }
+}
+@-webkit-keyframes mdui-spinner-layer-1-fade-in-out {
+  from {
+    opacity: 1;
+  }
+  25% {
+    opacity: 1;
+  }
+  26% {
+    opacity: 0;
+  }
+  89% {
+    opacity: 0;
+  }
+  90% {
+    opacity: 1;
+  }
+  100% {
+    opacity: 1;
+  }
+}
+@keyframes mdui-spinner-layer-1-fade-in-out {
+  from {
+    opacity: 1;
+  }
+  25% {
+    opacity: 1;
+  }
+  26% {
+    opacity: 0;
+  }
+  89% {
+    opacity: 0;
+  }
+  90% {
+    opacity: 1;
+  }
+  100% {
+    opacity: 1;
+  }
+}
+@-webkit-keyframes mdui-spinner-layer-2-fade-in-out {
+  from {
+    opacity: 0;
+  }
+  15% {
+    opacity: 0;
+  }
+  25% {
+    opacity: 1;
+  }
+  50% {
+    opacity: 1;
+  }
+  51% {
+    opacity: 0;
+  }
+}
+@keyframes mdui-spinner-layer-2-fade-in-out {
+  from {
+    opacity: 0;
+  }
+  15% {
+    opacity: 0;
+  }
+  25% {
+    opacity: 1;
+  }
+  50% {
+    opacity: 1;
+  }
+  51% {
+    opacity: 0;
+  }
+}
+@-webkit-keyframes mdui-spinner-layer-3-fade-in-out {
+  from {
+    opacity: 0;
+  }
+  40% {
+    opacity: 0;
+  }
+  50% {
+    opacity: 1;
+  }
+  75% {
+    opacity: 1;
+  }
+  76% {
+    opacity: 0;
+  }
+}
+@keyframes mdui-spinner-layer-3-fade-in-out {
+  from {
+    opacity: 0;
+  }
+  40% {
+    opacity: 0;
+  }
+  50% {
+    opacity: 1;
+  }
+  75% {
+    opacity: 1;
+  }
+  76% {
+    opacity: 0;
+  }
+}
+@-webkit-keyframes mdui-spinner-layer-4-fade-in-out {
+  from {
+    opacity: 0;
+  }
+  65% {
+    opacity: 0;
+  }
+  75% {
+    opacity: 1;
+  }
+  90% {
+    opacity: 1;
+  }
+  100% {
+    opacity: 0;
+  }
+}
+@keyframes mdui-spinner-layer-4-fade-in-out {
+  from {
+    opacity: 0;
+  }
+  65% {
+    opacity: 0;
+  }
+  75% {
+    opacity: 1;
+  }
+  90% {
+    opacity: 1;
+  }
+  100% {
+    opacity: 0;
+  }
+}
+.mdui-spinner-gap-patch {
+  position: absolute;
+  top: 0;
+  left: 45%;
+  width: 10%;
+  height: 100%;
+  overflow: hidden;
+  border-color: inherit;
+}
+.mdui-spinner-gap-patch .mdui-spinner-circle {
+  left: -450%;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 1000%;
+}
+.mdui-spinner-circle-clipper {
+  position: relative;
+  display: inline-block;
+  width: 50%;
+  height: 100%;
+  overflow: hidden;
+  border-color: inherit;
+}
+.mdui-spinner-circle-clipper .mdui-spinner-circle {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 200%;
+  height: 100%;
+  border-color: inherit;
+  border-style: solid;
+  border-width: 3px;
+  border-bottom-color: transparent !important;
+  border-radius: 50%;
+  -webkit-animation: none;
+          animation: none;
+}
+.mdui-spinner-circle-clipper.mdui-spinner-left {
+  float: left;
+}
+.mdui-spinner-circle-clipper.mdui-spinner-left .mdui-spinner-circle {
+  left: 0;
+  border-right-color: transparent !important;
+  -webkit-transform: rotate(129deg);
+          transform: rotate(129deg);
+  -webkit-animation: mdui-spinner-left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+          animation: mdui-spinner-left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+.mdui-spinner-circle-clipper.mdui-spinner-right {
+  float: right;
+}
+.mdui-spinner-circle-clipper.mdui-spinner-right .mdui-spinner-circle {
+  left: -100%;
+  border-left-color: transparent !important;
+  -webkit-transform: rotate(-129deg);
+          transform: rotate(-129deg);
+  -webkit-animation: mdui-spinner-right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+          animation: mdui-spinner-right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+@-webkit-keyframes mdui-spinner-left-spin {
+  from {
+    -webkit-transform: rotate(130deg);
+            transform: rotate(130deg);
+  }
+  50% {
+    -webkit-transform: rotate(-5deg);
+            transform: rotate(-5deg);
+  }
+  to {
+    -webkit-transform: rotate(130deg);
+            transform: rotate(130deg);
+  }
+}
+@keyframes mdui-spinner-left-spin {
+  from {
+    -webkit-transform: rotate(130deg);
+            transform: rotate(130deg);
+  }
+  50% {
+    -webkit-transform: rotate(-5deg);
+            transform: rotate(-5deg);
+  }
+  to {
+    -webkit-transform: rotate(130deg);
+            transform: rotate(130deg);
+  }
+}
+@-webkit-keyframes mdui-spinner-right-spin {
+  from {
+    -webkit-transform: rotate(-130deg);
+            transform: rotate(-130deg);
+  }
+  50% {
+    -webkit-transform: rotate(5deg);
+            transform: rotate(5deg);
+  }
+  to {
+    -webkit-transform: rotate(-130deg);
+            transform: rotate(-130deg);
+  }
+}
+@keyframes mdui-spinner-right-spin {
+  from {
+    -webkit-transform: rotate(-130deg);
+            transform: rotate(-130deg);
+  }
+  50% {
+    -webkit-transform: rotate(5deg);
+            transform: rotate(5deg);
+  }
+  to {
+    -webkit-transform: rotate(-130deg);
+            transform: rotate(-130deg);
+  }
+}
+/**
+ * =============================================================================
+ * ************   Spinner linear 主色   ************
+ * =============================================================================
+ */
+.mdui-theme-primary-amber .mdui-spinner-layer {
+  border-color: #FFC107;
+}
+.mdui-theme-primary-blue .mdui-spinner-layer {
+  border-color: #2196F3;
+}
+.mdui-theme-primary-blue-grey .mdui-spinner-layer {
+  border-color: #607D8B;
+}
+.mdui-theme-primary-brown .mdui-spinner-layer {
+  border-color: #795548;
+}
+.mdui-theme-primary-cyan .mdui-spinner-layer {
+  border-color: #00BCD4;
+}
+.mdui-theme-primary-deep-orange .mdui-spinner-layer {
+  border-color: #FF5722;
+}
+.mdui-theme-primary-deep-purple .mdui-spinner-layer {
+  border-color: #673AB7;
+}
+.mdui-theme-primary-green .mdui-spinner-layer {
+  border-color: #4CAF50;
+}
+.mdui-theme-primary-grey .mdui-spinner-layer {
+  border-color: #9E9E9E;
+}
+.mdui-theme-primary-indigo .mdui-spinner-layer {
+  border-color: #3F51B5;
+}
+.mdui-theme-primary-light-blue .mdui-spinner-layer {
+  border-color: #03A9F4;
+}
+.mdui-theme-primary-light-green .mdui-spinner-layer {
+  border-color: #8BC34A;
+}
+.mdui-theme-primary-lime .mdui-spinner-layer {
+  border-color: #CDDC39;
+}
+.mdui-theme-primary-orange .mdui-spinner-layer {
+  border-color: #FF9800;
+}
+.mdui-theme-primary-pink .mdui-spinner-layer {
+  border-color: #E91E63;
+}
+.mdui-theme-primary-purple .mdui-spinner-layer {
+  border-color: #9C27B0;
+}
+.mdui-theme-primary-red .mdui-spinner-layer {
+  border-color: #F44336;
+}
+.mdui-theme-primary-teal .mdui-spinner-layer {
+  border-color: #009688;
+}
+.mdui-theme-primary-yellow .mdui-spinner-layer {
+  border-color: #FFEB3B;
+}
+/**
+ * =============================================================================
+ * ************   Menu 菜单   ************
+ * =============================================================================
+ */
+/* 菜单 */
+.mdui-menu {
+  position: fixed;
+  z-index: 99999;
+  display: block;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 168px;
+  margin: 0;
+  padding: 8px 0;
+  overflow-y: auto;
+  color: rgba(0, 0, 0, 0.87);
+  font-size: 16px;
+  list-style: none;
+  background-color: #fff;
+  border-radius: 2px;
+  -webkit-transform: scale(0);
+          transform: scale(0);
+  visibility: hidden;
+  opacity: 0;
+  -webkit-transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
+          transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
+  -webkit-transition-duration: 0.3s;
+          transition-duration: 0.3s;
+  -webkit-transition-property: opacity, visibility, -webkit-transform;
+  transition-property: opacity, visibility, -webkit-transform;
+  transition-property: transform, opacity, visibility;
+  transition-property: transform, opacity, visibility, -webkit-transform;
+  will-change: transform, opacity, visibility;
+  -webkit-overflow-scrolling: touch;
+  -webkit-box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
+}
+.mdui-menu .mdui-divider {
+  margin-top: 8px;
+  margin-bottom: 8px;
+}
+/* 打开状态的菜单 */
+.mdui-menu-open {
+  -webkit-transform: scale(1);
+          transform: scale(1);
+  visibility: visible;
+  opacity: 1;
+}
+/* 关闭中的菜单 */
+.mdui-menu-closing {
+  -webkit-transform: scale(1);
+          transform: scale(1);
+  visibility: visible;
+  opacity: 0;
+}
+/* 菜单项 */
+.mdui-menu-item {
+  position: relative;
+}
+.mdui-menu-item > a {
+  position: relative;
+  display: block;
+  height: 48px;
+  padding: 0 16px;
+  color: inherit;
+  line-height: 48px;
+  text-decoration: none;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.mdui-menu-item > a:hover {
+  background-color: #EEEEEE;
+}
+.mdui-menu-item > .mdui-menu {
+  position: absolute;
+  -webkit-box-shadow: 0 5px 6px -3px rgba(0, 0, 0, 0.2), 0 9px 12px 1px rgba(0, 0, 0, 0.14), 0 3px 16px 2px rgba(0, 0, 0, 0.12);
+          box-shadow: 0 5px 6px -3px rgba(0, 0, 0, 0.2), 0 9px 12px 1px rgba(0, 0, 0, 0.14), 0 3px 16px 2px rgba(0, 0, 0, 0.12);
+}
+.mdui-menu-item[disabled] > a {
+  color: rgba(0, 0, 0, 0.38) !important;
+  cursor: default;
+}
+.mdui-menu-item[disabled] > a:hover {
+  background-color: inherit !important;
+}
+.mdui-menu-item[disabled] > a .mdui-icon {
+  color: rgba(0, 0, 0, 0.26);
+}
+/* 激活状态的菜单项 */
+.mdui-menu-item-active {
+  background-color: #EEEEEE;
+}
+/* 菜单中的图标 */
+.mdui-menu-item-icon {
+  display: inline-block;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  width: 40px;
+  padding-right: 16px;
+  color: rgba(0, 0, 0, 0.54);
+}
+/* 菜单中的辅助文本或图标 */
+.mdui-menu-item-helper {
+  float: right;
+}
+/* 有子菜单的条目的图标 */
+.mdui-menu-item-more {
+  float: right;
+  width: 24px;
+  height: 24px;
+  margin: 4px 0;
+  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M9.5 17.5l5-5-5-5z' opacity='.54'/%3E%3C/svg%3E");
+}
+/* 级联菜单 */
+.mdui-menu-cascade {
+  width: 320px;
+  padding: 16px 0;
+  overflow: visible;
+  font-size: 15px;
+}
+.mdui-menu-cascade > .mdui-menu-item > a {
+  height: 32px;
+  padding: 0 24px;
+  line-height: 32px;
+}
+/**
+ * =============================================================================
+ * ************   Menu dark   ************
+ * =============================================================================
+ */
+.mdui-theme-layout-dark .mdui-menu {
+  color: #fff;
+  background-color: #424242;
+}
+.mdui-theme-layout-dark .mdui-menu-item > a:hover {
+  background-color: #616161;
+}
+.mdui-theme-layout-dark .mdui-menu-item[disabled] > a {
+  color: rgba(255, 255, 255, 0.5) !important;
+}
+.mdui-theme-layout-dark .mdui-menu-item[disabled] > a .mdui-icon {
+  color: rgba(255, 255, 255, 0.3);
+}
+.mdui-theme-layout-dark .mdui-menu-item-active {
+  background-color: #616161;
+}
+.mdui-theme-layout-dark .mdui-menu-item-icon {
+  color: #ffffff;
+}
+.mdui-theme-layout-dark .mdui-menu-item-more {
+  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M9.5 17.5l5-5-5-5z' fill='%23FFF'/%3E%3C/svg%3E");
+}
+@media (prefers-color-scheme: dark) {
+  .mdui-theme-layout-auto .mdui-menu {
+    color: #fff;
+    background-color: #424242;
+  }
+  .mdui-theme-layout-auto .mdui-menu-item > a:hover {
+    background-color: #616161;
+  }
+  .mdui-theme-layout-auto .mdui-menu-item[disabled] > a {
+    color: rgba(255, 255, 255, 0.5) !important;
+  }
+  .mdui-theme-layout-auto .mdui-menu-item[disabled] > a .mdui-icon {
+    color: rgba(255, 255, 255, 0.3);
+  }
+  .mdui-theme-layout-auto .mdui-menu-item-active {
+    background-color: #616161;
+  }
+  .mdui-theme-layout-auto .mdui-menu-item-icon {
+    color: #ffffff;
+  }
+  .mdui-theme-layout-auto .mdui-menu-item-more {
+    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M9.5 17.5l5-5-5-5z' fill='%23FFF'/%3E%3C/svg%3E");
+  }
+}
+
+/*# sourceMappingURL=mdui.css.map */

File diff suppressed because it is too large
+ 0 - 0
koyeb/web/css/mdui.css.map


File diff suppressed because it is too large
+ 4 - 0
koyeb/web/css/mdui.min.css


File diff suppressed because it is too large
+ 0 - 0
koyeb/web/css/mdui.min.css.map


+ 201 - 0
koyeb/web/fonts/roboto/LICENSE.txt

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

BIN
koyeb/web/fonts/roboto/Roboto-Black.woff


BIN
koyeb/web/fonts/roboto/Roboto-Black.woff2


BIN
koyeb/web/fonts/roboto/Roboto-BlackItalic.woff


BIN
koyeb/web/fonts/roboto/Roboto-BlackItalic.woff2


BIN
koyeb/web/fonts/roboto/Roboto-Bold.woff


BIN
koyeb/web/fonts/roboto/Roboto-Bold.woff2


BIN
koyeb/web/fonts/roboto/Roboto-BoldItalic.woff


BIN
koyeb/web/fonts/roboto/Roboto-BoldItalic.woff2


BIN
koyeb/web/fonts/roboto/Roboto-Light.woff


BIN
koyeb/web/fonts/roboto/Roboto-Light.woff2


BIN
koyeb/web/fonts/roboto/Roboto-LightItalic.woff


BIN
koyeb/web/fonts/roboto/Roboto-LightItalic.woff2


BIN
koyeb/web/fonts/roboto/Roboto-Medium.woff


BIN
koyeb/web/fonts/roboto/Roboto-Medium.woff2


BIN
koyeb/web/fonts/roboto/Roboto-MediumItalic.woff


BIN
koyeb/web/fonts/roboto/Roboto-MediumItalic.woff2


BIN
koyeb/web/fonts/roboto/Roboto-Regular.woff


BIN
koyeb/web/fonts/roboto/Roboto-Regular.woff2


BIN
koyeb/web/fonts/roboto/Roboto-RegularItalic.woff


BIN
koyeb/web/fonts/roboto/Roboto-RegularItalic.woff2


BIN
koyeb/web/fonts/roboto/Roboto-Thin.woff


BIN
koyeb/web/fonts/roboto/Roboto-Thin.woff2


BIN
koyeb/web/fonts/roboto/Roboto-ThinItalic.woff


BIN
koyeb/web/fonts/roboto/Roboto-ThinItalic.woff2


+ 393 - 0
koyeb/web/icons/material-icons/LICENSE.txt

@@ -0,0 +1,393 @@
+Attribution 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+     Considerations for licensors: Our public licenses are
+     intended for use by those authorized to give the public
+     permission to use material in ways otherwise restricted by
+     copyright and certain other rights. Our licenses are
+     irrevocable. Licensors should read and understand the terms
+     and conditions of the license they choose before applying it.
+     Licensors should also secure all rights necessary before
+     applying our licenses so that the public can reuse the
+     material as expected. Licensors should clearly mark any
+     material not subject to the license. This includes other CC-
+     licensed material, or material used under an exception or
+     limitation to copyright. More considerations for licensors:
+	wiki.creativecommons.org/Considerations_for_licensors
+
+     Considerations for the public: By using one of our public
+     licenses, a licensor grants the public permission to use the
+     licensed material under specified terms and conditions. If
+     the licensor's permission is not necessary for any reason--for
+     example, because of any applicable exception or limitation to
+     copyright--then that use is not regulated by the license. Our
+     licenses grant only permissions under copyright and certain
+     other rights that a licensor has authority to grant. Use of
+     the licensed material may still be restricted for other
+     reasons, including because others have copyright or other
+     rights in the material. A licensor may make special requests,
+     such as asking that all changes be marked or described.
+     Although not required by our licenses, you are encouraged to
+     respect those requests where reasonable. More_considerations
+     for the public: 
+	wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution 4.0 International Public License ("Public License"). To the
+extent this Public License may be interpreted as a contract, You are
+granted the Licensed Rights in consideration of Your acceptance of
+these terms and conditions, and the Licensor grants You such rights in
+consideration of benefits the Licensor receives from making the
+Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+  a. Adapted Material means material subject to Copyright and Similar
+     Rights that is derived from or based upon the Licensed Material
+     and in which the Licensed Material is translated, altered,
+     arranged, transformed, or otherwise modified in a manner requiring
+     permission under the Copyright and Similar Rights held by the
+     Licensor. For purposes of this Public License, where the Licensed
+     Material is a musical work, performance, or sound recording,
+     Adapted Material is always produced where the Licensed Material is
+     synched in timed relation with a moving image.
+
+  b. Adapter's License means the license You apply to Your Copyright
+     and Similar Rights in Your contributions to Adapted Material in
+     accordance with the terms and conditions of this Public License.
+
+  c. Copyright and Similar Rights means copyright and/or similar rights
+     closely related to copyright including, without limitation,
+     performance, broadcast, sound recording, and Sui Generis Database
+     Rights, without regard to how the rights are labeled or
+     categorized. For purposes of this Public License, the rights
+     specified in Section 2(b)(1)-(2) are not Copyright and Similar
+     Rights.
+
+  d. Effective Technological Measures means those measures that, in the
+     absence of proper authority, may not be circumvented under laws
+     fulfilling obligations under Article 11 of the WIPO Copyright
+     Treaty adopted on December 20, 1996, and/or similar international
+     agreements.
+
+  e. Exceptions and Limitations means fair use, fair dealing, and/or
+     any other exception or limitation to Copyright and Similar Rights
+     that applies to Your use of the Licensed Material.
+
+  f. Licensed Material means the artistic or literary work, database,
+     or other material to which the Licensor applied this Public
+     License.
+
+  g. Licensed Rights means the rights granted to You subject to the
+     terms and conditions of this Public License, which are limited to
+     all Copyright and Similar Rights that apply to Your use of the
+     Licensed Material and that the Licensor has authority to license.
+
+  h. Licensor means the individual(s) or entity(ies) granting rights
+     under this Public License.
+
+  i. Share means to provide material to the public by any means or
+     process that requires permission under the Licensed Rights, such
+     as reproduction, public display, public performance, distribution,
+     dissemination, communication, or importation, and to make material
+     available to the public including in ways that members of the
+     public may access the material from a place and at a time
+     individually chosen by them.
+
+  j. Sui Generis Database Rights means rights other than copyright
+     resulting from Directive 96/9/EC of the European Parliament and of
+     the Council of 11 March 1996 on the legal protection of databases,
+     as amended and/or succeeded, as well as other essentially
+     equivalent rights anywhere in the world.
+
+  k. You means the individual or entity exercising the Licensed Rights
+     under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+  a. License grant.
+
+       1. Subject to the terms and conditions of this Public License,
+          the Licensor hereby grants You a worldwide, royalty-free,
+          non-sublicensable, non-exclusive, irrevocable license to
+          exercise the Licensed Rights in the Licensed Material to:
+
+            a. reproduce and Share the Licensed Material, in whole or
+               in part; and
+
+            b. produce, reproduce, and Share Adapted Material.
+
+       2. Exceptions and Limitations. For the avoidance of doubt, where
+          Exceptions and Limitations apply to Your use, this Public
+          License does not apply, and You do not need to comply with
+          its terms and conditions.
+
+       3. Term. The term of this Public License is specified in Section
+          6(a).
+
+       4. Media and formats; technical modifications allowed. The
+          Licensor authorizes You to exercise the Licensed Rights in
+          all media and formats whether now known or hereafter created,
+          and to make technical modifications necessary to do so. The
+          Licensor waives and/or agrees not to assert any right or
+          authority to forbid You from making technical modifications
+          necessary to exercise the Licensed Rights, including
+          technical modifications necessary to circumvent Effective
+          Technological Measures. For purposes of this Public License,
+          simply making modifications authorized by this Section 2(a)
+          (4) never produces Adapted Material.
+
+       5. Downstream recipients.
+
+            a. Offer from the Licensor -- Licensed Material. Every
+               recipient of the Licensed Material automatically
+               receives an offer from the Licensor to exercise the
+               Licensed Rights under the terms and conditions of this
+               Public License.
+
+            b. No downstream restrictions. You may not offer or impose
+               any additional or different terms or conditions on, or
+               apply any Effective Technological Measures to, the
+               Licensed Material if doing so restricts exercise of the
+               Licensed Rights by any recipient of the Licensed
+               Material.
+
+       6. No endorsement. Nothing in this Public License constitutes or
+          may be construed as permission to assert or imply that You
+          are, or that Your use of the Licensed Material is, connected
+          with, or sponsored, endorsed, or granted official status by,
+          the Licensor or others designated to receive attribution as
+          provided in Section 3(a)(1)(A)(i).
+
+  b. Other rights.
+
+       1. Moral rights, such as the right of integrity, are not
+          licensed under this Public License, nor are publicity,
+          privacy, and/or other similar personality rights; however, to
+          the extent possible, the Licensor waives and/or agrees not to
+          assert any such rights held by the Licensor to the limited
+          extent necessary to allow You to exercise the Licensed
+          Rights, but not otherwise.
+
+       2. Patent and trademark rights are not licensed under this
+          Public License.
+
+       3. To the extent possible, the Licensor waives any right to
+          collect royalties from You for the exercise of the Licensed
+          Rights, whether directly or through a collecting society
+          under any voluntary or waivable statutory or compulsory
+          licensing scheme. In all other cases the Licensor expressly
+          reserves any right to collect such royalties.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+  a. Attribution.
+
+       1. If You Share the Licensed Material (including in modified
+          form), You must:
+
+            a. retain the following if it is supplied by the Licensor
+               with the Licensed Material:
+
+                 i. identification of the creator(s) of the Licensed
+                    Material and any others designated to receive
+                    attribution, in any reasonable manner requested by
+                    the Licensor (including by pseudonym if
+                    designated);
+
+                ii. a copyright notice;
+
+               iii. a notice that refers to this Public License;
+
+                iv. a notice that refers to the disclaimer of
+                    warranties;
+
+                 v. a URI or hyperlink to the Licensed Material to the
+                    extent reasonably practicable;
+
+            b. indicate if You modified the Licensed Material and
+               retain an indication of any previous modifications; and
+
+            c. indicate the Licensed Material is licensed under this
+               Public License, and include the text of, or the URI or
+               hyperlink to, this Public License.
+
+       2. You may satisfy the conditions in Section 3(a)(1) in any
+          reasonable manner based on the medium, means, and context in
+          which You Share the Licensed Material. For example, it may be
+          reasonable to satisfy the conditions by providing a URI or
+          hyperlink to a resource that includes the required
+          information.
+
+       3. If requested by the Licensor, You must remove any of the
+          information required by Section 3(a)(1)(A) to the extent
+          reasonably practicable.
+
+       4. If You Share Adapted Material You produce, the Adapter's
+          License You apply must not prevent recipients of the Adapted
+          Material from complying with this Public License.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+  a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+     to extract, reuse, reproduce, and Share all or a substantial
+     portion of the contents of the database;
+
+  b. if You include all or a substantial portion of the database
+     contents in a database in which You have Sui Generis Database
+     Rights, then the database in which You have Sui Generis Database
+     Rights (but not its individual contents) is Adapted Material; and
+
+  c. You must comply with the conditions in Section 3(a) if You Share
+     all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+  c. The disclaimer of warranties and limitation of liability provided
+     above shall be interpreted in a manner that, to the extent
+     possible, most closely approximates an absolute disclaimer and
+     waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+  a. This Public License applies for the term of the Copyright and
+     Similar Rights licensed here. However, if You fail to comply with
+     this Public License, then Your rights under this Public License
+     terminate automatically.
+
+  b. Where Your right to use the Licensed Material has terminated under
+     Section 6(a), it reinstates:
+
+       1. automatically as of the date the violation is cured, provided
+          it is cured within 30 days of Your discovery of the
+          violation; or
+
+       2. upon express reinstatement by the Licensor.
+
+     For the avoidance of doubt, this Section 6(b) does not affect any
+     right the Licensor may have to seek remedies for Your violations
+     of this Public License.
+
+  c. For the avoidance of doubt, the Licensor may also offer the
+     Licensed Material under separate terms or conditions or stop
+     distributing the Licensed Material at any time; however, doing so
+     will not terminate this Public License.
+
+  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+     License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+  a. The Licensor shall not be bound by any additional or different
+     terms or conditions communicated by You unless expressly agreed.
+
+  b. Any arrangements, understandings, or agreements regarding the
+     Licensed Material not stated herein are separate from and
+     independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+  a. For the avoidance of doubt, this Public License does not, and
+     shall not be interpreted to, reduce, limit, restrict, or impose
+     conditions on any use of the Licensed Material that could lawfully
+     be made without permission under this Public License.
+
+  b. To the extent possible, if any provision of this Public License is
+     deemed unenforceable, it shall be automatically reformed to the
+     minimum extent necessary to make it enforceable. If the provision
+     cannot be reformed, it shall be severed from this Public License
+     without affecting the enforceability of the remaining terms and
+     conditions.
+
+  c. No term or condition of this Public License will be waived and no
+     failure to comply consented to unless expressly agreed to by the
+     Licensor.
+
+  d. Nothing in this Public License constitutes or may be interpreted
+     as a limitation upon, or waiver of, any privileges and immunities
+     that apply to the Licensor or You, including from the legal
+     processes of any jurisdiction or authority.
+
+
+=======================================================================
+
+Creative Commons is not a party to its public licenses.
+Notwithstanding, Creative Commons may elect to apply one of its public
+licenses to material it publishes and in those instances will be
+considered the "Licensor." Except for the limited purpose of indicating
+that material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the public
+licenses.
+
+Creative Commons may be contacted at creativecommons.org.

File diff suppressed because it is too large
+ 0 - 0
koyeb/web/icons/material-icons/MaterialIcons-Regular.ijmap


BIN
koyeb/web/icons/material-icons/MaterialIcons-Regular.woff


BIN
koyeb/web/icons/material-icons/MaterialIcons-Regular.woff2


BIN
koyeb/web/images/logo_bear.png


+ 349 - 0
koyeb/web/index.php

@@ -0,0 +1,349 @@
+<?php
+
+set_time_limit(0);
+
+header('X-Accel-Buffering: no');
+
+$FF_TOKEN = $_GET['ff-token'] ?? '';
+$VERIFIED = $FF_TOKEN === getenv('FF_TOKEN');
+
+require_once __DIR__ . '/vendor/autoload.php';
+
+use SensioLabs\AnsiConverter\AnsiToHtmlConverter;
+
+$converter = new AnsiToHtmlConverter();
+?>
+
+<!DOCTYPE html>
+<html lang="zh-cmn-Hans">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no"/>
+    <meta name="renderer" content="webkit"/>
+    <meta name="force-rendering" content="webkit"/>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
+    <title>Freenom 续期控制台 | 你只需部署,剩下的事情交给我们</title>
+    <link rel="stylesheet" href="css/mdui.min.css"/>
+    <style>
+        .loading-icon {
+            width: 17px;
+            height: 17px;
+            margin-right: 10px;
+            margin-top: -6px;
+            font-size: 18px;
+        }
+
+        .success-icon {
+            margin-top: -6px;
+            margin-right: 10px;
+        }
+
+        #copy-btn {
+            border-radius: 16px;
+        }
+
+        #output-box {
+            word-wrap: break-word;
+            font-size: 14px;
+        }
+
+        .a-tag {
+            color: #f44336;
+            text-decoration: none;
+            font-weight: bold;
+        }
+
+        @-webkit-keyframes shake {
+            0% {
+                opacity: 1;
+            }
+            50% {
+                opacity: 0;
+            }
+            100% {
+                opacity: 1;
+            }
+        }
+
+        @keyframes shake {
+            0% {
+                opacity: 1;
+            }
+            50% {
+                opacity: 0;
+            }
+            100% {
+                opacity: 1;
+            }
+        }
+
+        .shake {
+            -webkit-animation: shake 2s infinite;
+            animation: shake 2s infinite;
+        }
+    </style>
+</head>
+<body>
+<div class="mdui-container">
+    <div class="mdui-ripple mdui-ripple-yellow"
+         mdui-tooltip="{content: '前往项目 GitHub 仓库', position: 'auto', delay: 500}">
+        <a href="https://github.com/luolongfei/freenom" target="_blank">
+            <img class="mdui-img-rounded mdui-center mdui-valign mdui-img-fluid" src="images/logo_bear.png" alt="logo"/>
+        </a>
+    </div>
+
+    <ul class="mdui-list mdui-m-t-4">
+        <li class="mdui-list-item mdui-ripple mdui-shadow-1">
+            <div class="mdui-list-item-avatar">
+                <img src="https://q2.qlogo.cn/headimg_dl?dst_uin=593198779&spec=100" alt="作者头像"/>
+            </div>
+            <div class="mdui-list-item-content">
+                Freenom 续期控制台
+            </div>
+        </li>
+    </ul>
+
+    <?php if ($VERIFIED) { ?>
+    <div class="mdui-panel" mdui-panel>
+        <div class="mdui-panel-item mdui-panel-item-open">
+            <div class="mdui-panel-item-header">
+                注意事项
+            </div>
+            <div class="mdui-panel-item-body">
+                <p>1、当你看到我的时候,说明你已成功手动触发脚本执行</p>
+                <p>2、如果不想每次手动触发执行都输入 FF_TOKEN 的值,你也可以点击右边的按钮,以复制执行地址,下次访问执行地址即可触发脚本执行 <strong><span
+                                class="mdui-text-color-red" id="app-url"></span></strong>
+                    <button class="mdui-btn mdui-btn-raised mdui-btn-dense mdui-ripple mdui-color-pink-accent"
+                            id="copy-btn" data-clipboard-target="#app-url">
+                        复制地址
+                    </button>
+                </p>
+                <p>3、不要频繁刷新本页面,因为每次刷新都会手动触发脚本执行</p>
+                <p>4、手动触发脚本执行只是为了方便你快速测试部署是否成功,而容器内部的定时任务是会自动执行脚本的,所以,部署完成后,剩下的一切就交给程序吧</p>
+            </div>
+        </div>
+        <?php } else { ?>
+            <div class="mdui-panel" mdui-panel>
+                <div class="mdui-panel-item mdui-panel-item-open">
+                    <div class="mdui-panel-item-header">
+                        请先验证身份
+                    </div>
+                    <div class="mdui-panel-item-body">
+                        <div class="mdui-textfield mdui-textfield-floating-label">
+                            <i class="mdui-icon material-icons">lock</i>
+                            <label class="mdui-textfield-label" for="pwd">请输入你在 Koyeb 配置的 FF_TOKEN
+                                的值,即令牌</label>
+                            <input class="mdui-textfield-input" type="text" id="pwd"/>
+                            <div class="mdui-textfield-helper">
+                                点击上行文字即可输入内容,输入完成后,请点击下方送信按钮以验证身份
+                            </div>
+                        </div>
+                        <button class="mdui-btn mdui-btn-block mdui-color-red mdui-ripple" id="submit-btn">
+                            送信
+                        </button>
+                    </div>
+                </div>
+            </div>
+            <script>
+                let submitBtn = document.getElementById('submit-btn');
+
+                submitBtn.onclick = function () {
+                    let ffToken = document.getElementById('pwd').value;
+
+                    ffToken = ffToken.replace(/\s/g, '');
+
+                    if (ffToken.length < 1) {
+                        mdui.snackbar({message: '请输入令牌'});
+
+                        return;
+                    }
+
+                    submitBtn.disabled = true;
+                    submitBtn.innerText = '送信中...';
+
+                    window.location.href = '?ff-token=' + ffToken;
+                }
+            </script>
+        <?php } ?>
+
+        <div class="mdui-panel-item mdui-panel-item-open" id="shell-box">
+            <div class="mdui-panel-item-header" id="shell-title">
+                <div id="running-box">
+                    <i class="mdui-icon material-icons loading-icon mdui-text-color-red shake">fiber_manual_record</i>
+                    正在执行
+                </div>
+                <div id="success-box" style="display: none;">
+                    <i class="mdui-icon material-icons mdui-text-color-green-500 success-icon">check_circle</i>完成
+                </div>
+            </div>
+            <div class="mdui-panel-item-body mdui-color-black" id="output-box">
+                <?php
+                if ($VERIFIED) {
+                    echo '<p>Freenom 自动续期工具</p>';
+                    echo '<p>开始执行</p><br>';
+
+                    $cmd = 'php /app/run';
+
+                    while (@ob_end_flush()) ;
+
+                    $proc = popen($cmd, 'r');
+
+                    while (!feof($proc)) {
+                        echo '<p>' . $converter->convert(fread($proc, 4096)) . '</p>';
+                        @flush();
+                    }
+
+                    echo '<p>执行完了</p>';
+                    echo '<p>Made with <i class="mdui-icon material-icons mdui-text-color-pink-a200 shake">favorite</i> by <a class="mdui-text-color-white-text" href="https:\/\/github.com/luolongfei" target="_blank">luolongfei</a></p>';
+
+                    echo '<script type="text/javascript">',
+                    "document.getElementById('running-box').style.display = 'none';
+                    document.getElementById('success-box').style.display = 'block';",
+                    '</script>';
+                } else {
+                    echo '<p>你没有权限触发执行</p>';
+                    echo '<script type="text/javascript">',
+                    'document.getElementById("shell-title").innerHTML = "啊,出错啦";',
+                    '</script>';
+                }
+                ?>
+            </div>
+        </div>
+    </div>
+
+    <div class="mdui-dialog" id="donation-dialog">
+        <div class="mdui-dialog-content">
+            <ul class="mdui-list mdui-list-dense">
+                <li class="mdui-list-item mdui-ripple">
+                    <div class="mdui-list-item-avatar">
+                        <img src="https://q2.qlogo.cn/headimg_dl?dst_uin=593198779&spec=100" alt="作者头像"/>
+                    </div>
+                    <div class="mdui-list-item-content">
+                        <div class="mdui-list-item-title">Freenom 续期工具</div>
+                        <div class="mdui-list-item-text mdui-list-item-two-line">
+                            <span class="mdui-text-color-theme-text">如果你觉得本项目对你有帮助,请考虑赞助本项目。</span>
+                        </div>
+                    </div>
+                </li>
+            </ul>
+            <div class="mdui-card">
+                <div class="mdui-card-media">
+                    <img class="mdui-img-rounded" src="https://s2.ax1x.com/2020/01/31/1394at.png" alt="赞助二维码"/>
+                </div>
+
+                <div class="mdui-card-content">
+                    <div id="smart-button-container">
+                        <div style="text-align: center;">
+                            <div id="paypal-button-container"></div>
+                        </div>
+                    </div>
+
+                    <script type='text/javascript' src='https://storage.ko-fi.com/cdn/widget/Widget_2.js'></script>
+                    <script type='text/javascript'>kofiwidget2.init('Support Me on Ko-fi', '#F05D59', 'X7X8CA7S1');
+                        kofiwidget2.draw();</script>
+                </div>
+            </div>
+        </div>
+        <div class="mdui-dialog-actions">
+            <button class="mdui-btn mdui-ripple" mdui-dialog-close>不了</button>
+            <button class="mdui-btn mdui-ripple" mdui-dialog-close
+                    onclick="mdui.snackbar({message: '赞助在哪里,我没收到呢'});">已赞助
+            </button>
+        </div>
+    </div>
+</div>
+
+<div class="mdui-container">
+    <p>
+        <a href="https://github.com/luolongfei/freenom" target="_blank"
+           class="mdui-btn mdui-btn-raised mdui-ripple"><i class="mdui-icon material-icons">link</i>
+            访问仓库</a>
+        <a href="https://github.com/luolongfei/freenom/wiki/Donation-List"
+           class="mdui-btn mdui-btn-raised mdui-ripple mdui-color-theme-accent"
+           target="_blank"><i class="mdui-icon material-icons">format_list_bulleted</i>
+            赞助名单
+        </a>
+        <button class="mdui-btn mdui-btn-raised mdui-ripple mdui-color-theme-accent mdui-text-color-red"
+                mdui-dialog="{target: '#donation-dialog'}"><i class="mdui-icon material-icons">exposure_plus_1</i>
+            <strong>赞助作者</strong>
+        </button>
+    </p>
+</div>
+
+<script src="js/mdui.min.js"></script>
+<script src="js/clipboard.min.js"></script>
+<script src="https://www.paypal.com/sdk/js?client-id=sb&enable-funding=venmo&currency=USD"
+        data-sdk-integration-source="button-factory"></script>
+
+<?php
+
+if ($FF_TOKEN !== '' && !$VERIFIED) { // 验证失败
+    echo '<script type="text/javascript">',
+    "mdui.snackbar({message: '你输入的令牌有误,请重试'});",
+    '</script>';
+}
+
+if ($VERIFIED) { // 验证成功
+    ?>
+
+    <script type="text/javascript">
+        document.getElementById('app-url').innerHTML = `https://${document.domain}/?ff-token=<?php echo $FF_TOKEN; ?>`;
+
+        let clipboard = new ClipboardJS('#copy-btn');
+        clipboard.on('success', function (e) {
+            console.info('Action:', e.action);
+            console.info('Text:', e.text);
+            console.info('Trigger:', e.trigger);
+            mdui.snackbar({message: '复制成功'});
+
+            e.clearSelection();
+        });
+        clipboard.on('error', function (e) {
+            console.error('Action:', e.action);
+            console.error('Trigger:', e.trigger);
+            alert('复制失败,请手动复制');
+        });
+
+        setTimeout(function () {
+            document.getElementById('shell-box').scrollIntoView({behavior: 'smooth', block: 'start', inline: 'start'});
+        }, 1500);
+    </script>
+
+    <?php
+}
+?>
+<script>
+    function initPayPalButton() {
+        paypal.Buttons({
+            style: {
+                shape: 'rect',
+                color: 'gold',
+                layout: 'horizontal',
+                label: 'paypal',
+
+            },
+            createOrder: function (data, actions) {
+                return actions.order.create({
+                    purchase_units: [{
+                        "description": "赞助 freenom 自动续期脚本的作者,以促进项目持续发展。",
+                        "amount": {"currency_code": "USD", "value": 5}
+                    }]
+                });
+            },
+            onApprove: function (data, actions) {
+                return actions.order.capture().then(function (orderData) {
+                    const element = document.getElementById('paypal-button-container');
+                    element.innerHTML = '';
+                    element.innerHTML = '<h3>Thank you for your payment!</h3>';
+                });
+            },
+            onError: function (err) {
+                console.log(err);
+            }
+        }).render('#paypal-button-container');
+    }
+
+    initPayPalButton();
+</script>
+</body>
+</html>

File diff suppressed because it is too large
+ 6 - 0
koyeb/web/js/clipboard.min.js


+ 5976 - 0
koyeb/web/js/mdui.esm.js

@@ -0,0 +1,5976 @@
+/*!
+ * mdui 1.0.2 (https://mdui.org)
+ * Copyright 2016-2021 zdhxiong
+ * Licensed under MIT
+ */
+function isFunction(target) {
+    return typeof target === 'function';
+}
+function isString(target) {
+    return typeof target === 'string';
+}
+function isNumber(target) {
+    return typeof target === 'number';
+}
+function isBoolean(target) {
+    return typeof target === 'boolean';
+}
+function isUndefined(target) {
+    return typeof target === 'undefined';
+}
+function isNull(target) {
+    return target === null;
+}
+function isWindow(target) {
+    return target instanceof Window;
+}
+function isDocument(target) {
+    return target instanceof Document;
+}
+function isElement(target) {
+    return target instanceof Element;
+}
+function isNode(target) {
+    return target instanceof Node;
+}
+/**
+ * 是否是 IE 浏览器
+ */
+function isIE() {
+    // @ts-ignore
+    return !!window.document.documentMode;
+}
+function isArrayLike(target) {
+    if (isFunction(target) || isWindow(target)) {
+        return false;
+    }
+    return isNumber(target.length);
+}
+function isObjectLike(target) {
+    return typeof target === 'object' && target !== null;
+}
+function toElement(target) {
+    return isDocument(target) ? target.documentElement : target;
+}
+/**
+ * 把用 - 分隔的字符串转为驼峰(如 box-sizing 转换为 boxSizing)
+ * @param string
+ */
+function toCamelCase(string) {
+    return string
+        .replace(/^-ms-/, 'ms-')
+        .replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
+}
+/**
+ * 把驼峰法转为用 - 分隔的字符串(如 boxSizing 转换为 box-sizing)
+ * @param string
+ */
+function toKebabCase(string) {
+    return string.replace(/[A-Z]/g, (replacer) => '-' + replacer.toLowerCase());
+}
+/**
+ * 获取元素的样式值
+ * @param element
+ * @param name
+ */
+function getComputedStyleValue(element, name) {
+    return window.getComputedStyle(element).getPropertyValue(toKebabCase(name));
+}
+/**
+ * 检查元素的 box-sizing 是否是 border-box
+ * @param element
+ */
+function isBorderBox(element) {
+    return getComputedStyleValue(element, 'box-sizing') === 'border-box';
+}
+/**
+ * 获取元素的 padding, border, margin 宽度(两侧宽度的和,单位为px)
+ * @param element
+ * @param direction
+ * @param extra
+ */
+function getExtraWidth(element, direction, extra) {
+    const position = direction === 'width' ? ['Left', 'Right'] : ['Top', 'Bottom'];
+    return [0, 1].reduce((prev, _, index) => {
+        let prop = extra + position[index];
+        if (extra === 'border') {
+            prop += 'Width';
+        }
+        return prev + parseFloat(getComputedStyleValue(element, prop) || '0');
+    }, 0);
+}
+/**
+ * 获取元素的样式值,对 width 和 height 进行过处理
+ * @param element
+ * @param name
+ */
+function getStyle(element, name) {
+    // width、height 属性使用 getComputedStyle 得到的值不准确,需要使用 getBoundingClientRect 获取
+    if (name === 'width' || name === 'height') {
+        const valueNumber = element.getBoundingClientRect()[name];
+        if (isBorderBox(element)) {
+            return `${valueNumber}px`;
+        }
+        return `${valueNumber -
+            getExtraWidth(element, name, 'border') -
+            getExtraWidth(element, name, 'padding')}px`;
+    }
+    return getComputedStyleValue(element, name);
+}
+/**
+ * 获取子节点组成的数组
+ * @param target
+ * @param parent
+ */
+function getChildNodesArray(target, parent) {
+    const tempParent = document.createElement(parent);
+    tempParent.innerHTML = target;
+    return [].slice.call(tempParent.childNodes);
+}
+/**
+ * 始终返回 false 的函数
+ */
+function returnFalse() {
+    return false;
+}
+/**
+ * 数值单位的 CSS 属性
+ */
+const cssNumber = [
+    'animationIterationCount',
+    'columnCount',
+    'fillOpacity',
+    'flexGrow',
+    'flexShrink',
+    'fontWeight',
+    'gridArea',
+    'gridColumn',
+    'gridColumnEnd',
+    'gridColumnStart',
+    'gridRow',
+    'gridRowEnd',
+    'gridRowStart',
+    'lineHeight',
+    'opacity',
+    'order',
+    'orphans',
+    'widows',
+    'zIndex',
+    'zoom',
+];
+
+function each(target, callback) {
+    if (isArrayLike(target)) {
+        for (let i = 0; i < target.length; i += 1) {
+            if (callback.call(target[i], i, target[i]) === false) {
+                return target;
+            }
+        }
+    }
+    else {
+        const keys = Object.keys(target);
+        for (let i = 0; i < keys.length; i += 1) {
+            if (callback.call(target[keys[i]], keys[i], target[keys[i]]) === false) {
+                return target;
+            }
+        }
+    }
+    return target;
+}
+
+/**
+ * 为了使用模块扩充,这里不能使用默认导出
+ */
+class JQ {
+    constructor(arr) {
+        this.length = 0;
+        if (!arr) {
+            return this;
+        }
+        each(arr, (i, item) => {
+            // @ts-ignore
+            this[i] = item;
+        });
+        this.length = arr.length;
+        return this;
+    }
+}
+
+function get$() {
+    const $ = function (selector) {
+        if (!selector) {
+            return new JQ();
+        }
+        // JQ
+        if (selector instanceof JQ) {
+            return selector;
+        }
+        // function
+        if (isFunction(selector)) {
+            if (/complete|loaded|interactive/.test(document.readyState) &&
+                document.body) {
+                selector.call(document, $);
+            }
+            else {
+                document.addEventListener('DOMContentLoaded', () => selector.call(document, $), false);
+            }
+            return new JQ([document]);
+        }
+        // String
+        if (isString(selector)) {
+            const html = selector.trim();
+            // 根据 HTML 字符串创建 JQ 对象
+            if (html[0] === '<' && html[html.length - 1] === '>') {
+                let toCreate = 'div';
+                const tags = {
+                    li: 'ul',
+                    tr: 'tbody',
+                    td: 'tr',
+                    th: 'tr',
+                    tbody: 'table',
+                    option: 'select',
+                };
+                each(tags, (childTag, parentTag) => {
+                    if (html.indexOf(`<${childTag}`) === 0) {
+                        toCreate = parentTag;
+                        return false;
+                    }
+                    return;
+                });
+                return new JQ(getChildNodesArray(html, toCreate));
+            }
+            // 根据 CSS 选择器创建 JQ 对象
+            const isIdSelector = selector[0] === '#' && !selector.match(/[ .<>:~]/);
+            if (!isIdSelector) {
+                return new JQ(document.querySelectorAll(selector));
+            }
+            const element = document.getElementById(selector.slice(1));
+            if (element) {
+                return new JQ([element]);
+            }
+            return new JQ();
+        }
+        if (isArrayLike(selector) && !isNode(selector)) {
+            return new JQ(selector);
+        }
+        return new JQ([selector]);
+    };
+    $.fn = JQ.prototype;
+    return $;
+}
+const $ = get$();
+
+// 避免页面加载完后直接执行css动画
+// https://css-tricks.com/transitions-only-after-page-load/
+setTimeout(() => $('body').addClass('mdui-loaded'));
+const mdui = {
+    $: $,
+};
+
+$.fn.each = function (callback) {
+    return each(this, callback);
+};
+
+/**
+ * 检查 container 元素内是否包含 contains 元素
+ * @param container 父元素
+ * @param contains 子元素
+ * @example
+```js
+contains( document, document.body ); // true
+contains( document.getElementById('test'), document ); // false
+contains( $('.container').get(0), $('.contains').get(0) ); // false
+```
+ */
+function contains(container, contains) {
+    return container !== contains && toElement(container).contains(contains);
+}
+
+/**
+ * 把第二个数组的元素追加到第一个数组中,并返回合并后的数组
+ * @param first 第一个数组
+ * @param second 该数组的元素将被追加到第一个数组中
+ * @example
+```js
+merge( [ 0, 1, 2 ], [ 2, 3, 4 ] )
+// [ 0, 1, 2, 2, 3, 4 ]
+```
+ */
+function merge(first, second) {
+    each(second, (_, value) => {
+        first.push(value);
+    });
+    return first;
+}
+
+$.fn.get = function (index) {
+    return index === undefined
+        ? [].slice.call(this)
+        : this[index >= 0 ? index : index + this.length];
+};
+
+$.fn.find = function (selector) {
+    const foundElements = [];
+    this.each((_, element) => {
+        merge(foundElements, $(element.querySelectorAll(selector)).get());
+    });
+    return new JQ(foundElements);
+};
+
+// 存储事件
+const handlers = {};
+// 元素ID
+let mduiElementId = 1;
+/**
+ * 为元素赋予一个唯一的ID
+ */
+function getElementId(element) {
+    const key = '_mduiEventId';
+    // @ts-ignore
+    if (!element[key]) {
+        // @ts-ignore
+        element[key] = ++mduiElementId;
+    }
+    // @ts-ignore
+    return element[key];
+}
+/**
+ * 解析事件名中的命名空间
+ */
+function parse(type) {
+    const parts = type.split('.');
+    return {
+        type: parts[0],
+        ns: parts.slice(1).sort().join(' '),
+    };
+}
+/**
+ * 命名空间匹配规则
+ */
+function matcherFor(ns) {
+    return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)');
+}
+/**
+ * 获取匹配的事件
+ * @param element
+ * @param type
+ * @param func
+ * @param selector
+ */
+function getHandlers(element, type, func, selector) {
+    const event = parse(type);
+    return (handlers[getElementId(element)] || []).filter((handler) => handler &&
+        (!event.type || handler.type === event.type) &&
+        (!event.ns || matcherFor(event.ns).test(handler.ns)) &&
+        (!func || getElementId(handler.func) === getElementId(func)) &&
+        (!selector || handler.selector === selector));
+}
+/**
+ * 添加事件监听
+ * @param element
+ * @param types
+ * @param func
+ * @param data
+ * @param selector
+ */
+function add(element, types, func, data, selector) {
+    const elementId = getElementId(element);
+    if (!handlers[elementId]) {
+        handlers[elementId] = [];
+    }
+    // 传入 data.useCapture 来设置 useCapture: true
+    let useCapture = false;
+    if (isObjectLike(data) && data.useCapture) {
+        useCapture = true;
+    }
+    types.split(' ').forEach((type) => {
+        if (!type) {
+            return;
+        }
+        const event = parse(type);
+        function callFn(e, elem) {
+            // 因为鼠标事件模拟事件的 detail 属性是只读的,因此在 e._detail 中存储参数
+            const result = func.apply(elem, 
+            // @ts-ignore
+            e._detail === undefined ? [e] : [e].concat(e._detail));
+            if (result === false) {
+                e.preventDefault();
+                e.stopPropagation();
+            }
+        }
+        function proxyFn(e) {
+            // @ts-ignore
+            if (e._ns && !matcherFor(e._ns).test(event.ns)) {
+                return;
+            }
+            // @ts-ignore
+            e._data = data;
+            if (selector) {
+                // 事件代理
+                $(element)
+                    .find(selector)
+                    .get()
+                    .reverse()
+                    .forEach((elem) => {
+                    if (elem === e.target ||
+                        contains(elem, e.target)) {
+                        callFn(e, elem);
+                    }
+                });
+            }
+            else {
+                // 不使用事件代理
+                callFn(e, element);
+            }
+        }
+        const handler = {
+            type: event.type,
+            ns: event.ns,
+            func,
+            selector,
+            id: handlers[elementId].length,
+            proxy: proxyFn,
+        };
+        handlers[elementId].push(handler);
+        element.addEventListener(handler.type, proxyFn, useCapture);
+    });
+}
+/**
+ * 移除事件监听
+ * @param element
+ * @param types
+ * @param func
+ * @param selector
+ */
+function remove(element, types, func, selector) {
+    const handlersInElement = handlers[getElementId(element)] || [];
+    const removeEvent = (handler) => {
+        delete handlersInElement[handler.id];
+        element.removeEventListener(handler.type, handler.proxy, false);
+    };
+    if (!types) {
+        handlersInElement.forEach((handler) => removeEvent(handler));
+    }
+    else {
+        types.split(' ').forEach((type) => {
+            if (type) {
+                getHandlers(element, type, func, selector).forEach((handler) => removeEvent(handler));
+            }
+        });
+    }
+}
+
+$.fn.trigger = function (type, extraParameters) {
+    const event = parse(type);
+    let eventObject;
+    const eventParams = {
+        bubbles: true,
+        cancelable: true,
+    };
+    const isMouseEvent = ['click', 'mousedown', 'mouseup', 'mousemove'].indexOf(event.type) > -1;
+    if (isMouseEvent) {
+        // Note: MouseEvent 无法传入 detail 参数
+        eventObject = new MouseEvent(event.type, eventParams);
+    }
+    else {
+        eventParams.detail = extraParameters;
+        eventObject = new CustomEvent(event.type, eventParams);
+    }
+    // @ts-ignore
+    eventObject._detail = extraParameters;
+    // @ts-ignore
+    eventObject._ns = event.ns;
+    return this.each(function () {
+        this.dispatchEvent(eventObject);
+    });
+};
+
+function extend(target, object1, ...objectN) {
+    objectN.unshift(object1);
+    each(objectN, (_, object) => {
+        each(object, (prop, value) => {
+            if (!isUndefined(value)) {
+                target[prop] = value;
+            }
+        });
+    });
+    return target;
+}
+
+/**
+ * 将数组或对象序列化,序列化后的字符串可作为 URL 查询字符串使用
+ *
+ * 若传入数组,则格式必须和 serializeArray 方法的返回值一样
+ * @param obj 对象或数组
+ * @example
+```js
+param({ width: 1680, height: 1050 });
+// width=1680&height=1050
+```
+ * @example
+```js
+param({ foo: { one: 1, two: 2 }})
+// foo[one]=1&foo[two]=2
+```
+ * @example
+```js
+param({ids: [1, 2, 3]})
+// ids[]=1&ids[]=2&ids[]=3
+```
+ * @example
+```js
+param([
+  {"name":"name","value":"mdui"},
+  {"name":"password","value":"123456"}
+])
+// name=mdui&password=123456
+```
+ */
+function param(obj) {
+    if (!isObjectLike(obj) && !Array.isArray(obj)) {
+        return '';
+    }
+    const args = [];
+    function destructure(key, value) {
+        let keyTmp;
+        if (isObjectLike(value)) {
+            each(value, (i, v) => {
+                if (Array.isArray(value) && !isObjectLike(v)) {
+                    keyTmp = '';
+                }
+                else {
+                    keyTmp = i;
+                }
+                destructure(`${key}[${keyTmp}]`, v);
+            });
+        }
+        else {
+            if (value == null || value === '') {
+                keyTmp = '=';
+            }
+            else {
+                keyTmp = `=${encodeURIComponent(value)}`;
+            }
+            args.push(encodeURIComponent(key) + keyTmp);
+        }
+    }
+    if (Array.isArray(obj)) {
+        each(obj, function () {
+            destructure(this.name, this.value);
+        });
+    }
+    else {
+        each(obj, destructure);
+    }
+    return args.join('&');
+}
+
+// 全局配置参数
+const globalOptions = {};
+// 全局事件名
+const ajaxEvents = {
+    ajaxStart: 'start.mdui.ajax',
+    ajaxSuccess: 'success.mdui.ajax',
+    ajaxError: 'error.mdui.ajax',
+    ajaxComplete: 'complete.mdui.ajax',
+};
+
+/**
+ * 判断此请求方法是否通过查询字符串提交参数
+ * @param method 请求方法,大写
+ */
+function isQueryStringData(method) {
+    return ['GET', 'HEAD'].indexOf(method) >= 0;
+}
+/**
+ * 添加参数到 URL 上,且 URL 中不存在 ? 时,自动把第一个 & 替换为 ?
+ * @param url
+ * @param query
+ */
+function appendQuery(url, query) {
+    return `${url}&${query}`.replace(/[&?]{1,2}/, '?');
+}
+/**
+ * 合并请求参数,参数优先级:options > globalOptions > defaults
+ * @param options
+ */
+function mergeOptions(options) {
+    // 默认参数
+    const defaults = {
+        url: '',
+        method: 'GET',
+        data: '',
+        processData: true,
+        async: true,
+        cache: true,
+        username: '',
+        password: '',
+        headers: {},
+        xhrFields: {},
+        statusCode: {},
+        dataType: 'text',
+        contentType: 'application/x-www-form-urlencoded',
+        timeout: 0,
+        global: true,
+    };
+    // globalOptions 中的回调函数不合并
+    each(globalOptions, (key, value) => {
+        const callbacks = [
+            'beforeSend',
+            'success',
+            'error',
+            'complete',
+            'statusCode',
+        ];
+        // @ts-ignore
+        if (callbacks.indexOf(key) < 0 && !isUndefined(value)) {
+            defaults[key] = value;
+        }
+    });
+    return extend({}, defaults, options);
+}
+/**
+ * 发送 ajax 请求
+ * @param options
+ * @example
+```js
+ajax({
+  method: "POST",
+  url: "some.php",
+  data: { name: "John", location: "Boston" }
+}).then(function( msg ) {
+  alert( "Data Saved: " + msg );
+});
+```
+ */
+function ajax(options) {
+    // 是否已取消请求
+    let isCanceled = false;
+    // 事件参数
+    const eventParams = {};
+    // 参数合并
+    const mergedOptions = mergeOptions(options);
+    let url = mergedOptions.url || window.location.toString();
+    const method = mergedOptions.method.toUpperCase();
+    let data = mergedOptions.data;
+    const processData = mergedOptions.processData;
+    const async = mergedOptions.async;
+    const cache = mergedOptions.cache;
+    const username = mergedOptions.username;
+    const password = mergedOptions.password;
+    const headers = mergedOptions.headers;
+    const xhrFields = mergedOptions.xhrFields;
+    const statusCode = mergedOptions.statusCode;
+    const dataType = mergedOptions.dataType;
+    const contentType = mergedOptions.contentType;
+    const timeout = mergedOptions.timeout;
+    const global = mergedOptions.global;
+    // 需要发送的数据
+    // GET/HEAD 请求和 processData 为 true 时,转换为查询字符串格式,特殊格式不转换
+    if (data &&
+        (isQueryStringData(method) || processData) &&
+        !isString(data) &&
+        !(data instanceof ArrayBuffer) &&
+        !(data instanceof Blob) &&
+        !(data instanceof Document) &&
+        !(data instanceof FormData)) {
+        data = param(data);
+    }
+    // 对于 GET、HEAD 类型的请求,把 data 数据添加到 URL 中
+    if (data && isQueryStringData(method)) {
+        // 查询字符串拼接到 URL 中
+        url = appendQuery(url, data);
+        data = null;
+    }
+    /**
+     * 触发事件和回调函数
+     * @param event
+     * @param params
+     * @param callback
+     * @param args
+     */
+    function trigger(event, params, callback, ...args) {
+        // 触发全局事件
+        if (global) {
+            $(document).trigger(event, params);
+        }
+        // 触发 ajax 回调和事件
+        let result1;
+        let result2;
+        if (callback) {
+            // 全局回调
+            if (callback in globalOptions) {
+                // @ts-ignore
+                result1 = globalOptions[callback](...args);
+            }
+            // 自定义回调
+            if (mergedOptions[callback]) {
+                // @ts-ignore
+                result2 = mergedOptions[callback](...args);
+            }
+            // beforeSend 回调返回 false 时取消 ajax 请求
+            if (callback === 'beforeSend' &&
+                (result1 === false || result2 === false)) {
+                isCanceled = true;
+            }
+        }
+    }
+    // XMLHttpRequest 请求
+    function XHR() {
+        let textStatus;
+        return new Promise((resolve, reject) => {
+            // GET/HEAD 请求的缓存处理
+            if (isQueryStringData(method) && !cache) {
+                url = appendQuery(url, `_=${Date.now()}`);
+            }
+            // 创建 XHR
+            const xhr = new XMLHttpRequest();
+            xhr.open(method, url, async, username, password);
+            if (contentType ||
+                (data && !isQueryStringData(method) && contentType !== false)) {
+                xhr.setRequestHeader('Content-Type', contentType);
+            }
+            // 设置 Accept
+            if (dataType === 'json') {
+                xhr.setRequestHeader('Accept', 'application/json, text/javascript');
+            }
+            // 添加 headers
+            if (headers) {
+                each(headers, (key, value) => {
+                    // undefined 值不发送,string 和 null 需要发送
+                    if (!isUndefined(value)) {
+                        xhr.setRequestHeader(key, value + ''); // 把 null 转换成字符串
+                    }
+                });
+            }
+            // 检查是否是跨域请求,跨域请求时不添加 X-Requested-With
+            const crossDomain = /^([\w-]+:)?\/\/([^/]+)/.test(url) &&
+                RegExp.$2 !== window.location.host;
+            if (!crossDomain) {
+                xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+            }
+            if (xhrFields) {
+                each(xhrFields, (key, value) => {
+                    // @ts-ignore
+                    xhr[key] = value;
+                });
+            }
+            eventParams.xhr = xhr;
+            eventParams.options = mergedOptions;
+            let xhrTimeout;
+            xhr.onload = function () {
+                if (xhrTimeout) {
+                    clearTimeout(xhrTimeout);
+                }
+                // AJAX 返回的 HTTP 响应码是否表示成功
+                const isHttpStatusSuccess = (xhr.status >= 200 && xhr.status < 300) ||
+                    xhr.status === 304 ||
+                    xhr.status === 0;
+                let responseData;
+                if (isHttpStatusSuccess) {
+                    if (xhr.status === 204 || method === 'HEAD') {
+                        textStatus = 'nocontent';
+                    }
+                    else if (xhr.status === 304) {
+                        textStatus = 'notmodified';
+                    }
+                    else {
+                        textStatus = 'success';
+                    }
+                    if (dataType === 'json') {
+                        try {
+                            responseData =
+                                method === 'HEAD' ? undefined : JSON.parse(xhr.responseText);
+                            eventParams.data = responseData;
+                        }
+                        catch (err) {
+                            textStatus = 'parsererror';
+                            trigger(ajaxEvents.ajaxError, eventParams, 'error', xhr, textStatus);
+                            reject(new Error(textStatus));
+                        }
+                        if (textStatus !== 'parsererror') {
+                            trigger(ajaxEvents.ajaxSuccess, eventParams, 'success', responseData, textStatus, xhr);
+                            resolve(responseData);
+                        }
+                    }
+                    else {
+                        responseData =
+                            method === 'HEAD'
+                                ? undefined
+                                : xhr.responseType === 'text' || xhr.responseType === ''
+                                    ? xhr.responseText
+                                    : xhr.response;
+                        eventParams.data = responseData;
+                        trigger(ajaxEvents.ajaxSuccess, eventParams, 'success', responseData, textStatus, xhr);
+                        resolve(responseData);
+                    }
+                }
+                else {
+                    textStatus = 'error';
+                    trigger(ajaxEvents.ajaxError, eventParams, 'error', xhr, textStatus);
+                    reject(new Error(textStatus));
+                }
+                // statusCode
+                each([globalOptions.statusCode, statusCode], (_, func) => {
+                    if (func && func[xhr.status]) {
+                        if (isHttpStatusSuccess) {
+                            func[xhr.status](responseData, textStatus, xhr);
+                        }
+                        else {
+                            func[xhr.status](xhr, textStatus);
+                        }
+                    }
+                });
+                trigger(ajaxEvents.ajaxComplete, eventParams, 'complete', xhr, textStatus);
+            };
+            xhr.onerror = function () {
+                if (xhrTimeout) {
+                    clearTimeout(xhrTimeout);
+                }
+                trigger(ajaxEvents.ajaxError, eventParams, 'error', xhr, xhr.statusText);
+                trigger(ajaxEvents.ajaxComplete, eventParams, 'complete', xhr, 'error');
+                reject(new Error(xhr.statusText));
+            };
+            xhr.onabort = function () {
+                let statusText = 'abort';
+                if (xhrTimeout) {
+                    statusText = 'timeout';
+                    clearTimeout(xhrTimeout);
+                }
+                trigger(ajaxEvents.ajaxError, eventParams, 'error', xhr, statusText);
+                trigger(ajaxEvents.ajaxComplete, eventParams, 'complete', xhr, statusText);
+                reject(new Error(statusText));
+            };
+            // ajax start 回调
+            trigger(ajaxEvents.ajaxStart, eventParams, 'beforeSend', xhr);
+            if (isCanceled) {
+                reject(new Error('cancel'));
+                return;
+            }
+            // Timeout
+            if (timeout > 0) {
+                xhrTimeout = setTimeout(() => {
+                    xhr.abort();
+                }, timeout);
+            }
+            // 发送 XHR
+            xhr.send(data);
+        });
+    }
+    return XHR();
+}
+
+$.ajax = ajax;
+
+/**
+ * 为 Ajax 请求设置全局配置参数
+ * @param options 键值对参数
+ * @example
+```js
+ajaxSetup({
+  dataType: 'json',
+  method: 'POST',
+});
+```
+ */
+function ajaxSetup(options) {
+    return extend(globalOptions, options);
+}
+
+$.ajaxSetup = ajaxSetup;
+
+$.contains = contains;
+
+const dataNS = '_mduiElementDataStorage';
+
+/**
+ * 在元素上设置键值对数据
+ * @param element
+ * @param object
+ */
+function setObjectToElement(element, object) {
+    // @ts-ignore
+    if (!element[dataNS]) {
+        // @ts-ignore
+        element[dataNS] = {};
+    }
+    each(object, (key, value) => {
+        // @ts-ignore
+        element[dataNS][toCamelCase(key)] = value;
+    });
+}
+function data(element, key, value) {
+    // 根据键值对设置值
+    // data(element, { 'key' : 'value' })
+    if (isObjectLike(key)) {
+        setObjectToElement(element, key);
+        return key;
+    }
+    // 根据 key、value 设置值
+    // data(element, 'key', 'value')
+    if (!isUndefined(value)) {
+        setObjectToElement(element, { [key]: value });
+        return value;
+    }
+    // 获取所有值
+    // data(element)
+    if (isUndefined(key)) {
+        // @ts-ignore
+        return element[dataNS] ? element[dataNS] : {};
+    }
+    // 从 dataNS 中获取指定值
+    // data(element, 'key')
+    key = toCamelCase(key);
+    // @ts-ignore
+    if (element[dataNS] && key in element[dataNS]) {
+        // @ts-ignore
+        return element[dataNS][key];
+    }
+    return undefined;
+}
+
+$.data = data;
+
+$.each = each;
+
+$.extend = function (...objectN) {
+    if (objectN.length === 1) {
+        each(objectN[0], (prop, value) => {
+            this[prop] = value;
+        });
+        return this;
+    }
+    return extend(objectN.shift(), objectN.shift(), ...objectN);
+};
+
+function map(elements, callback) {
+    let value;
+    const ret = [];
+    each(elements, (i, element) => {
+        value = callback.call(window, element, i);
+        if (value != null) {
+            ret.push(value);
+        }
+    });
+    return [].concat(...ret);
+}
+
+$.map = map;
+
+$.merge = merge;
+
+$.param = param;
+
+/**
+ * 移除指定元素上存放的数据
+ * @param element 存放数据的元素
+ * @param name
+ * 数据键名
+ *
+ * 若未指定键名,将移除元素上所有数据
+ *
+ * 多个键名可以用空格分隔,或者用数组表示多个键名
+  @example
+```js
+// 移除元素上键名为 name 的数据
+removeData(document.body, 'name');
+```
+ * @example
+```js
+// 移除元素上键名为 name1 和 name2 的数据
+removeData(document.body, 'name1 name2');
+```
+ * @example
+```js
+// 移除元素上键名为 name1 和 name2 的数据
+removeData(document.body, ['name1', 'name2']);
+```
+ * @example
+```js
+// 移除元素上所有数据
+removeData(document.body);
+```
+ */
+function removeData(element, name) {
+    // @ts-ignore
+    if (!element[dataNS]) {
+        return;
+    }
+    const remove = (nameItem) => {
+        nameItem = toCamelCase(nameItem);
+        // @ts-ignore
+        if (element[dataNS][nameItem]) {
+            // @ts-ignore
+            element[dataNS][nameItem] = null;
+            // @ts-ignore
+            delete element[dataNS][nameItem];
+        }
+    };
+    if (isUndefined(name)) {
+        // @ts-ignore
+        element[dataNS] = null;
+        // @ts-ignore
+        delete element[dataNS];
+        // @ts-ignore
+    }
+    else if (isString(name)) {
+        name
+            .split(' ')
+            .filter((nameItem) => nameItem)
+            .forEach((nameItem) => remove(nameItem));
+    }
+    else {
+        each(name, (_, nameItem) => remove(nameItem));
+    }
+}
+
+$.removeData = removeData;
+
+/**
+ * 过滤掉数组中的重复元素
+ * @param arr 数组
+ * @example
+```js
+unique([1, 2, 12, 3, 2, 1, 2, 1, 1]);
+// [1, 2, 12, 3]
+```
+ */
+function unique(arr) {
+    const result = [];
+    each(arr, (_, val) => {
+        if (result.indexOf(val) === -1) {
+            result.push(val);
+        }
+    });
+    return result;
+}
+
+$.unique = unique;
+
+$.fn.add = function (selector) {
+    return new JQ(unique(merge(this.get(), $(selector).get())));
+};
+
+each(['add', 'remove', 'toggle'], (_, name) => {
+    $.fn[`${name}Class`] = function (className) {
+        if (name === 'remove' && !arguments.length) {
+            return this.each((_, element) => {
+                element.setAttribute('class', '');
+            });
+        }
+        return this.each((i, element) => {
+            if (!isElement(element)) {
+                return;
+            }
+            const classes = (isFunction(className)
+                ? className.call(element, i, element.getAttribute('class') || '')
+                : className)
+                .split(' ')
+                .filter((name) => name);
+            each(classes, (_, cls) => {
+                element.classList[name](cls);
+            });
+        });
+    };
+});
+
+each(['insertBefore', 'insertAfter'], (nameIndex, name) => {
+    $.fn[name] = function (target) {
+        const $element = nameIndex ? $(this.get().reverse()) : this; // 顺序和 jQuery 保持一致
+        const $target = $(target);
+        const result = [];
+        $target.each((index, target) => {
+            if (!target.parentNode) {
+                return;
+            }
+            $element.each((_, element) => {
+                const newItem = index
+                    ? element.cloneNode(true)
+                    : element;
+                const existingItem = nameIndex ? target.nextSibling : target;
+                result.push(newItem);
+                target.parentNode.insertBefore(newItem, existingItem);
+            });
+        });
+        return $(nameIndex ? result.reverse() : result);
+    };
+});
+
+/**
+ * 是否不是 HTML 字符串(包裹在 <> 中)
+ * @param target
+ */
+function isPlainText(target) {
+    return (isString(target) && (target[0] !== '<' || target[target.length - 1] !== '>'));
+}
+each(['before', 'after'], (nameIndex, name) => {
+    $.fn[name] = function (...args) {
+        // after 方法,多个参数需要按参数顺序添加到元素后面,所以需要将参数顺序反向处理
+        if (nameIndex === 1) {
+            args = args.reverse();
+        }
+        return this.each((index, element) => {
+            const targets = isFunction(args[0])
+                ? [args[0].call(element, index, element.innerHTML)]
+                : args;
+            each(targets, (_, target) => {
+                let $target;
+                if (isPlainText(target)) {
+                    $target = $(getChildNodesArray(target, 'div'));
+                }
+                else if (index && isElement(target)) {
+                    $target = $(target.cloneNode(true));
+                }
+                else {
+                    $target = $(target);
+                }
+                $target[nameIndex ? 'insertAfter' : 'insertBefore'](element);
+            });
+        });
+    };
+});
+
+$.fn.off = function (types, selector, callback) {
+    // types 是对象
+    if (isObjectLike(types)) {
+        each(types, (type, fn) => {
+            // this.off('click', undefined, function () {})
+            // this.off('click', '.box', function () {})
+            this.off(type, selector, fn);
+        });
+        return this;
+    }
+    // selector 不存在
+    if (selector === false || isFunction(selector)) {
+        callback = selector;
+        selector = undefined;
+        // this.off('click', undefined, function () {})
+    }
+    // callback 传入 `false`,相当于 `return false`
+    if (callback === false) {
+        callback = returnFalse;
+    }
+    return this.each(function () {
+        remove(this, types, callback, selector);
+    });
+};
+
+$.fn.on = function (types, selector, data, callback, one) {
+    // types 可以是 type/func 对象
+    if (isObjectLike(types)) {
+        // (types-Object, selector, data)
+        if (!isString(selector)) {
+            // (types-Object, data)
+            data = data || selector;
+            selector = undefined;
+        }
+        each(types, (type, fn) => {
+            // selector 和 data 都可能是 undefined
+            // @ts-ignore
+            this.on(type, selector, data, fn, one);
+        });
+        return this;
+    }
+    if (data == null && callback == null) {
+        // (types, fn)
+        callback = selector;
+        data = selector = undefined;
+    }
+    else if (callback == null) {
+        if (isString(selector)) {
+            // (types, selector, fn)
+            callback = data;
+            data = undefined;
+        }
+        else {
+            // (types, data, fn)
+            callback = data;
+            data = selector;
+            selector = undefined;
+        }
+    }
+    if (callback === false) {
+        callback = returnFalse;
+    }
+    else if (!callback) {
+        return this;
+    }
+    // $().one()
+    if (one) {
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        const _this = this;
+        const origCallback = callback;
+        callback = function (event) {
+            _this.off(event.type, selector, callback);
+            // eslint-disable-next-line prefer-rest-params
+            return origCallback.apply(this, arguments);
+        };
+    }
+    return this.each(function () {
+        add(this, types, callback, data, selector);
+    });
+};
+
+each(ajaxEvents, (name, eventName) => {
+    $.fn[name] = function (fn) {
+        return this.on(eventName, (e, params) => {
+            fn(e, params.xhr, params.options, params.data);
+        });
+    };
+});
+
+$.fn.map = function (callback) {
+    return new JQ(map(this, (element, i) => callback.call(element, i, element)));
+};
+
+$.fn.clone = function () {
+    return this.map(function () {
+        return this.cloneNode(true);
+    });
+};
+
+$.fn.is = function (selector) {
+    let isMatched = false;
+    if (isFunction(selector)) {
+        this.each((index, element) => {
+            if (selector.call(element, index, element)) {
+                isMatched = true;
+            }
+        });
+        return isMatched;
+    }
+    if (isString(selector)) {
+        this.each((_, element) => {
+            if (isDocument(element) || isWindow(element)) {
+                return;
+            }
+            // @ts-ignore
+            const matches = element.matches || element.msMatchesSelector;
+            if (matches.call(element, selector)) {
+                isMatched = true;
+            }
+        });
+        return isMatched;
+    }
+    const $compareWith = $(selector);
+    this.each((_, element) => {
+        $compareWith.each((_, compare) => {
+            if (element === compare) {
+                isMatched = true;
+            }
+        });
+    });
+    return isMatched;
+};
+
+$.fn.remove = function (selector) {
+    return this.each((_, element) => {
+        if (element.parentNode && (!selector || $(element).is(selector))) {
+            element.parentNode.removeChild(element);
+        }
+    });
+};
+
+each(['prepend', 'append'], (nameIndex, name) => {
+    $.fn[name] = function (...args) {
+        return this.each((index, element) => {
+            const childNodes = element.childNodes;
+            const childLength = childNodes.length;
+            const child = childLength
+                ? childNodes[nameIndex ? childLength - 1 : 0]
+                : document.createElement('div');
+            if (!childLength) {
+                element.appendChild(child);
+            }
+            let contents = isFunction(args[0])
+                ? [args[0].call(element, index, element.innerHTML)]
+                : args;
+            // 如果不是字符串,则仅第一个元素使用原始元素,其他的都克隆自第一个元素
+            if (index) {
+                contents = contents.map((content) => {
+                    return isString(content) ? content : $(content).clone();
+                });
+            }
+            $(child)[nameIndex ? 'after' : 'before'](...contents);
+            if (!childLength) {
+                element.removeChild(child);
+            }
+        });
+    };
+});
+
+each(['appendTo', 'prependTo'], (nameIndex, name) => {
+    $.fn[name] = function (target) {
+        const extraChilds = [];
+        const $target = $(target).map((_, element) => {
+            const childNodes = element.childNodes;
+            const childLength = childNodes.length;
+            if (childLength) {
+                return childNodes[nameIndex ? 0 : childLength - 1];
+            }
+            const child = document.createElement('div');
+            element.appendChild(child);
+            extraChilds.push(child);
+            return child;
+        });
+        const $result = this[nameIndex ? 'insertBefore' : 'insertAfter']($target);
+        $(extraChilds).remove();
+        return $result;
+    };
+});
+
+each(['attr', 'prop', 'css'], (nameIndex, name) => {
+    function set(element, key, value) {
+        // 值为 undefined 时,不修改
+        if (isUndefined(value)) {
+            return;
+        }
+        switch (nameIndex) {
+            // attr
+            case 0:
+                if (isNull(value)) {
+                    element.removeAttribute(key);
+                }
+                else {
+                    element.setAttribute(key, value);
+                }
+                break;
+            // prop
+            case 1:
+                // @ts-ignore
+                element[key] = value;
+                break;
+            // css
+            default:
+                key = toCamelCase(key);
+                // @ts-ignore
+                element.style[key] = isNumber(value)
+                    ? `${value}${cssNumber.indexOf(key) > -1 ? '' : 'px'}`
+                    : value;
+                break;
+        }
+    }
+    function get(element, key) {
+        switch (nameIndex) {
+            // attr
+            case 0:
+                // 属性不存在时,原生 getAttribute 方法返回 null,而 jquery 返回 undefined。这里和 jquery 保持一致
+                const value = element.getAttribute(key);
+                return isNull(value) ? undefined : value;
+            // prop
+            case 1:
+                // @ts-ignore
+                return element[key];
+            // css
+            default:
+                return getStyle(element, key);
+        }
+    }
+    $.fn[name] = function (key, value) {
+        if (isObjectLike(key)) {
+            each(key, (k, v) => {
+                // @ts-ignore
+                this[name](k, v);
+            });
+            return this;
+        }
+        if (arguments.length === 1) {
+            const element = this[0];
+            return isElement(element) ? get(element, key) : undefined;
+        }
+        return this.each((i, element) => {
+            set(element, key, isFunction(value) ? value.call(element, i, get(element, key)) : value);
+        });
+    };
+});
+
+$.fn.children = function (selector) {
+    const children = [];
+    this.each((_, element) => {
+        each(element.childNodes, (__, childNode) => {
+            if (!isElement(childNode)) {
+                return;
+            }
+            if (!selector || $(childNode).is(selector)) {
+                children.push(childNode);
+            }
+        });
+    });
+    return new JQ(unique(children));
+};
+
+$.fn.slice = function (...args) {
+    return new JQ([].slice.apply(this, args));
+};
+
+$.fn.eq = function (index) {
+    const ret = index === -1 ? this.slice(index) : this.slice(index, +index + 1);
+    return new JQ(ret);
+};
+
+function dir($elements, nameIndex, node, selector, filter) {
+    const ret = [];
+    let target;
+    $elements.each((_, element) => {
+        target = element[node];
+        // 不能包含最顶层的 document 元素
+        while (target && isElement(target)) {
+            // prevUntil, nextUntil, parentsUntil
+            if (nameIndex === 2) {
+                if (selector && $(target).is(selector)) {
+                    break;
+                }
+                if (!filter || $(target).is(filter)) {
+                    ret.push(target);
+                }
+            }
+            // prev, next, parent
+            else if (nameIndex === 0) {
+                if (!selector || $(target).is(selector)) {
+                    ret.push(target);
+                }
+                break;
+            }
+            // prevAll, nextAll, parents
+            else {
+                if (!selector || $(target).is(selector)) {
+                    ret.push(target);
+                }
+            }
+            // @ts-ignore
+            target = target[node];
+        }
+    });
+    return new JQ(unique(ret));
+}
+
+each(['', 's', 'sUntil'], (nameIndex, name) => {
+    $.fn[`parent${name}`] = function (selector, filter) {
+        // parents、parentsUntil 需要把元素的顺序反向处理,以便和 jQuery 的结果一致
+        const $nodes = !nameIndex ? this : $(this.get().reverse());
+        return dir($nodes, nameIndex, 'parentNode', selector, filter);
+    };
+});
+
+$.fn.closest = function (selector) {
+    if (this.is(selector)) {
+        return this;
+    }
+    const matched = [];
+    this.parents().each((_, element) => {
+        if ($(element).is(selector)) {
+            matched.push(element);
+            return false;
+        }
+    });
+    return new JQ(matched);
+};
+
+const rbrace = /^(?:{[\w\W]*\}|\[[\w\W]*\])$/;
+// 从 `data-*` 中获取的值,需要经过该函数转换
+function getData(value) {
+    if (value === 'true') {
+        return true;
+    }
+    if (value === 'false') {
+        return false;
+    }
+    if (value === 'null') {
+        return null;
+    }
+    if (value === +value + '') {
+        return +value;
+    }
+    if (rbrace.test(value)) {
+        return JSON.parse(value);
+    }
+    return value;
+}
+// 若 value 不存在,则从 `data-*` 中获取值
+function dataAttr(element, key, value) {
+    if (isUndefined(value) && element.nodeType === 1) {
+        const name = 'data-' + toKebabCase(key);
+        value = element.getAttribute(name);
+        if (isString(value)) {
+            try {
+                value = getData(value);
+            }
+            catch (e) { }
+        }
+        else {
+            value = undefined;
+        }
+    }
+    return value;
+}
+$.fn.data = function (key, value) {
+    // 获取所有值
+    if (isUndefined(key)) {
+        if (!this.length) {
+            return undefined;
+        }
+        const element = this[0];
+        const resultData = data(element);
+        // window, document 上不存在 `data-*` 属性
+        if (element.nodeType !== 1) {
+            return resultData;
+        }
+        // 从 `data-*` 中获取值
+        const attrs = element.attributes;
+        let i = attrs.length;
+        while (i--) {
+            if (attrs[i]) {
+                let name = attrs[i].name;
+                if (name.indexOf('data-') === 0) {
+                    name = toCamelCase(name.slice(5));
+                    resultData[name] = dataAttr(element, name, resultData[name]);
+                }
+            }
+        }
+        return resultData;
+    }
+    // 同时设置多个值
+    if (isObjectLike(key)) {
+        return this.each(function () {
+            data(this, key);
+        });
+    }
+    // value 传入了 undefined
+    if (arguments.length === 2 && isUndefined(value)) {
+        return this;
+    }
+    // 设置值
+    if (!isUndefined(value)) {
+        return this.each(function () {
+            data(this, key, value);
+        });
+    }
+    // 获取值
+    if (!this.length) {
+        return undefined;
+    }
+    return dataAttr(this[0], key, data(this[0], key));
+};
+
+$.fn.empty = function () {
+    return this.each(function () {
+        this.innerHTML = '';
+    });
+};
+
+$.fn.extend = function (obj) {
+    each(obj, (prop, value) => {
+        // 在 JQ 对象上扩展方法时,需要自己添加 typescript 的类型定义
+        $.fn[prop] = value;
+    });
+    return this;
+};
+
+$.fn.filter = function (selector) {
+    if (isFunction(selector)) {
+        return this.map((index, element) => selector.call(element, index, element) ? element : undefined);
+    }
+    if (isString(selector)) {
+        return this.map((_, element) => $(element).is(selector) ? element : undefined);
+    }
+    const $selector = $(selector);
+    return this.map((_, element) => $selector.get().indexOf(element) > -1 ? element : undefined);
+};
+
+$.fn.first = function () {
+    return this.eq(0);
+};
+
+$.fn.has = function (selector) {
+    const $targets = isString(selector) ? this.find(selector) : $(selector);
+    const { length } = $targets;
+    return this.map(function () {
+        for (let i = 0; i < length; i += 1) {
+            if (contains(this, $targets[i])) {
+                return this;
+            }
+        }
+        return;
+    });
+};
+
+$.fn.hasClass = function (className) {
+    return this[0].classList.contains(className);
+};
+
+/**
+ * 值上面的 padding、border、margin 处理
+ * @param element
+ * @param name
+ * @param value
+ * @param funcIndex
+ * @param includeMargin
+ * @param multiply
+ */
+function handleExtraWidth(element, name, value, funcIndex, includeMargin, multiply) {
+    // 获取元素的 padding, border, margin 宽度(两侧宽度的和)
+    const getExtraWidthValue = (extra) => {
+        return (getExtraWidth(element, name.toLowerCase(), extra) *
+            multiply);
+    };
+    if (funcIndex === 2 && includeMargin) {
+        value += getExtraWidthValue('margin');
+    }
+    if (isBorderBox(element)) {
+        // IE 为 box-sizing: border-box 时,得到的值不含 border 和 padding,这里先修复
+        // 仅获取时需要处理,multiply === 1 为 get
+        if (isIE() && multiply === 1) {
+            value += getExtraWidthValue('border');
+            value += getExtraWidthValue('padding');
+        }
+        if (funcIndex === 0) {
+            value -= getExtraWidthValue('border');
+        }
+        if (funcIndex === 1) {
+            value -= getExtraWidthValue('border');
+            value -= getExtraWidthValue('padding');
+        }
+    }
+    else {
+        if (funcIndex === 0) {
+            value += getExtraWidthValue('padding');
+        }
+        if (funcIndex === 2) {
+            value += getExtraWidthValue('border');
+            value += getExtraWidthValue('padding');
+        }
+    }
+    return value;
+}
+/**
+ * 获取元素的样式值
+ * @param element
+ * @param name
+ * @param funcIndex 0: innerWidth, innerHeight; 1: width, height; 2: outerWidth, outerHeight
+ * @param includeMargin
+ */
+function get(element, name, funcIndex, includeMargin) {
+    const clientProp = `client${name}`;
+    const scrollProp = `scroll${name}`;
+    const offsetProp = `offset${name}`;
+    const innerProp = `inner${name}`;
+    // $(window).width()
+    if (isWindow(element)) {
+        // outerWidth, outerHeight 需要包含滚动条的宽度
+        return funcIndex === 2
+            ? element[innerProp]
+            : toElement(document)[clientProp];
+    }
+    // $(document).width()
+    if (isDocument(element)) {
+        const doc = toElement(element);
+        return Math.max(
+        // @ts-ignore
+        element.body[scrollProp], doc[scrollProp], 
+        // @ts-ignore
+        element.body[offsetProp], doc[offsetProp], doc[clientProp]);
+    }
+    const value = parseFloat(getComputedStyleValue(element, name.toLowerCase()) || '0');
+    return handleExtraWidth(element, name, value, funcIndex, includeMargin, 1);
+}
+/**
+ * 设置元素的样式值
+ * @param element
+ * @param elementIndex
+ * @param name
+ * @param funcIndex 0: innerWidth, innerHeight; 1: width, height; 2: outerWidth, outerHeight
+ * @param includeMargin
+ * @param value
+ */
+function set(element, elementIndex, name, funcIndex, includeMargin, value) {
+    let computedValue = isFunction(value)
+        ? value.call(element, elementIndex, get(element, name, funcIndex, includeMargin))
+        : value;
+    if (computedValue == null) {
+        return;
+    }
+    const $element = $(element);
+    const dimension = name.toLowerCase();
+    // 特殊的值,不需要计算 padding、border、margin
+    if (['auto', 'inherit', ''].indexOf(computedValue) > -1) {
+        $element.css(dimension, computedValue);
+        return;
+    }
+    // 其他值保留原始单位。注意:如果不使用 px 作为单位,则算出的值一般是不准确的
+    const suffix = computedValue.toString().replace(/\b[0-9.]*/, '');
+    const numerical = parseFloat(computedValue);
+    computedValue =
+        handleExtraWidth(element, name, numerical, funcIndex, includeMargin, -1) +
+            (suffix || 'px');
+    $element.css(dimension, computedValue);
+}
+each(['Width', 'Height'], (_, name) => {
+    each([`inner${name}`, name.toLowerCase(), `outer${name}`], (funcIndex, funcName) => {
+        $.fn[funcName] = function (margin, value) {
+            // 是否是赋值操作
+            const isSet = arguments.length && (funcIndex < 2 || !isBoolean(margin));
+            const includeMargin = margin === true || value === true;
+            // 获取第一个元素的值
+            if (!isSet) {
+                return this.length
+                    ? get(this[0], name, funcIndex, includeMargin)
+                    : undefined;
+            }
+            // 设置每个元素的值
+            return this.each((index, element) => set(element, index, name, funcIndex, includeMargin, margin));
+        };
+    });
+});
+
+$.fn.hide = function () {
+    return this.each(function () {
+        this.style.display = 'none';
+    });
+};
+
+each(['val', 'html', 'text'], (nameIndex, name) => {
+    const props = {
+        0: 'value',
+        1: 'innerHTML',
+        2: 'textContent',
+    };
+    const propName = props[nameIndex];
+    function get($elements) {
+        // text() 获取所有元素的文本
+        if (nameIndex === 2) {
+            // @ts-ignore
+            return map($elements, (element) => toElement(element)[propName]).join('');
+        }
+        // 空集合时,val() 和 html() 返回 undefined
+        if (!$elements.length) {
+            return undefined;
+        }
+        // val() 和 html() 仅获取第一个元素的内容
+        const firstElement = $elements[0];
+        // select multiple 返回数组
+        if (nameIndex === 0 && $(firstElement).is('select[multiple]')) {
+            return map($(firstElement).find('option:checked'), (element) => element.value);
+        }
+        // @ts-ignore
+        return firstElement[propName];
+    }
+    function set(element, value) {
+        // text() 和 html() 赋值为 undefined,则保持原内容不变
+        // val() 赋值为 undefined 则赋值为空
+        if (isUndefined(value)) {
+            if (nameIndex !== 0) {
+                return;
+            }
+            value = '';
+        }
+        if (nameIndex === 1 && isElement(value)) {
+            value = value.outerHTML;
+        }
+        // @ts-ignore
+        element[propName] = value;
+    }
+    $.fn[name] = function (value) {
+        // 获取值
+        if (!arguments.length) {
+            return get(this);
+        }
+        // 设置值
+        return this.each((i, element) => {
+            const computedValue = isFunction(value)
+                ? value.call(element, i, get($(element)))
+                : value;
+            // value 是数组,则选中数组中的元素,反选不在数组中的元素
+            if (nameIndex === 0 && Array.isArray(computedValue)) {
+                // select[multiple]
+                if ($(element).is('select[multiple]')) {
+                    map($(element).find('option'), (option) => (option.selected =
+                        computedValue.indexOf(option.value) >
+                            -1));
+                }
+                // 其他 checkbox, radio 等元素
+                else {
+                    element.checked =
+                        computedValue.indexOf(element.value) > -1;
+                }
+            }
+            else {
+                set(element, computedValue);
+            }
+        });
+    };
+});
+
+$.fn.index = function (selector) {
+    if (!arguments.length) {
+        return this.eq(0).parent().children().get().indexOf(this[0]);
+    }
+    if (isString(selector)) {
+        return $(selector).get().indexOf(this[0]);
+    }
+    return this.get().indexOf($(selector)[0]);
+};
+
+$.fn.last = function () {
+    return this.eq(-1);
+};
+
+each(['', 'All', 'Until'], (nameIndex, name) => {
+    $.fn[`next${name}`] = function (selector, filter) {
+        return dir(this, nameIndex, 'nextElementSibling', selector, filter);
+    };
+});
+
+$.fn.not = function (selector) {
+    const $excludes = this.filter(selector);
+    return this.map((_, element) => $excludes.index(element) > -1 ? undefined : element);
+};
+
+/**
+ * 返回最近的用于定位的父元素
+ */
+$.fn.offsetParent = function () {
+    return this.map(function () {
+        let offsetParent = this.offsetParent;
+        while (offsetParent && $(offsetParent).css('position') === 'static') {
+            offsetParent = offsetParent.offsetParent;
+        }
+        return offsetParent || document.documentElement;
+    });
+};
+
+function floatStyle($element, name) {
+    return parseFloat($element.css(name));
+}
+$.fn.position = function () {
+    if (!this.length) {
+        return undefined;
+    }
+    const $element = this.eq(0);
+    let currentOffset;
+    let parentOffset = {
+        left: 0,
+        top: 0,
+    };
+    if ($element.css('position') === 'fixed') {
+        currentOffset = $element[0].getBoundingClientRect();
+    }
+    else {
+        currentOffset = $element.offset();
+        const $offsetParent = $element.offsetParent();
+        parentOffset = $offsetParent.offset();
+        parentOffset.top += floatStyle($offsetParent, 'border-top-width');
+        parentOffset.left += floatStyle($offsetParent, 'border-left-width');
+    }
+    return {
+        top: currentOffset.top - parentOffset.top - floatStyle($element, 'margin-top'),
+        left: currentOffset.left -
+            parentOffset.left -
+            floatStyle($element, 'margin-left'),
+    };
+};
+
+function get$1(element) {
+    if (!element.getClientRects().length) {
+        return { top: 0, left: 0 };
+    }
+    const rect = element.getBoundingClientRect();
+    const win = element.ownerDocument.defaultView;
+    return {
+        top: rect.top + win.pageYOffset,
+        left: rect.left + win.pageXOffset,
+    };
+}
+function set$1(element, value, index) {
+    const $element = $(element);
+    const position = $element.css('position');
+    if (position === 'static') {
+        $element.css('position', 'relative');
+    }
+    const currentOffset = get$1(element);
+    const currentTopString = $element.css('top');
+    const currentLeftString = $element.css('left');
+    let currentTop;
+    let currentLeft;
+    const calculatePosition = (position === 'absolute' || position === 'fixed') &&
+        (currentTopString + currentLeftString).indexOf('auto') > -1;
+    if (calculatePosition) {
+        const currentPosition = $element.position();
+        currentTop = currentPosition.top;
+        currentLeft = currentPosition.left;
+    }
+    else {
+        currentTop = parseFloat(currentTopString);
+        currentLeft = parseFloat(currentLeftString);
+    }
+    const computedValue = isFunction(value)
+        ? value.call(element, index, extend({}, currentOffset))
+        : value;
+    $element.css({
+        top: computedValue.top != null
+            ? computedValue.top - currentOffset.top + currentTop
+            : undefined,
+        left: computedValue.left != null
+            ? computedValue.left - currentOffset.left + currentLeft
+            : undefined,
+    });
+}
+$.fn.offset = function (value) {
+    // 获取坐标
+    if (!arguments.length) {
+        if (!this.length) {
+            return undefined;
+        }
+        return get$1(this[0]);
+    }
+    // 设置坐标
+    return this.each(function (index) {
+        set$1(this, value, index);
+    });
+};
+
+$.fn.one = function (types, selector, data, callback) {
+    // @ts-ignore
+    return this.on(types, selector, data, callback, true);
+};
+
+each(['', 'All', 'Until'], (nameIndex, name) => {
+    $.fn[`prev${name}`] = function (selector, filter) {
+        // prevAll、prevUntil 需要把元素的顺序倒序处理,以便和 jQuery 的结果一致
+        const $nodes = !nameIndex ? this : $(this.get().reverse());
+        return dir($nodes, nameIndex, 'previousElementSibling', selector, filter);
+    };
+});
+
+$.fn.removeAttr = function (attributeName) {
+    const names = attributeName.split(' ').filter((name) => name);
+    return this.each(function () {
+        each(names, (_, name) => {
+            this.removeAttribute(name);
+        });
+    });
+};
+
+$.fn.removeData = function (name) {
+    return this.each(function () {
+        removeData(this, name);
+    });
+};
+
+$.fn.removeProp = function (name) {
+    return this.each(function () {
+        try {
+            // @ts-ignore
+            delete this[name];
+        }
+        catch (e) { }
+    });
+};
+
+$.fn.replaceWith = function (newContent) {
+    this.each((index, element) => {
+        let content = newContent;
+        if (isFunction(content)) {
+            content = content.call(element, index, element.innerHTML);
+        }
+        else if (index && !isString(content)) {
+            content = $(content).clone();
+        }
+        $(element).before(content);
+    });
+    return this.remove();
+};
+
+$.fn.replaceAll = function (target) {
+    return $(target).map((index, element) => {
+        $(element).replaceWith(index ? this.clone() : this);
+        return this.get();
+    });
+};
+
+/**
+ * 将表单元素的值组合成键值对数组
+ * @returns {Array}
+ */
+$.fn.serializeArray = function () {
+    const result = [];
+    this.each((_, element) => {
+        const elements = element instanceof HTMLFormElement ? element.elements : [element];
+        $(elements).each((_, element) => {
+            const $element = $(element);
+            const type = element.type;
+            const nodeName = element.nodeName.toLowerCase();
+            if (nodeName !== 'fieldset' &&
+                element.name &&
+                !element.disabled &&
+                ['input', 'select', 'textarea', 'keygen'].indexOf(nodeName) > -1 &&
+                ['submit', 'button', 'image', 'reset', 'file'].indexOf(type) === -1 &&
+                (['radio', 'checkbox'].indexOf(type) === -1 ||
+                    element.checked)) {
+                const value = $element.val();
+                const valueArr = Array.isArray(value) ? value : [value];
+                valueArr.forEach((value) => {
+                    result.push({
+                        name: element.name,
+                        value,
+                    });
+                });
+            }
+        });
+    });
+    return result;
+};
+
+$.fn.serialize = function () {
+    return param(this.serializeArray());
+};
+
+const elementDisplay = {};
+/**
+ * 获取元素的初始 display 值,用于 .show() 方法
+ * @param nodeName
+ */
+function defaultDisplay(nodeName) {
+    let element;
+    let display;
+    if (!elementDisplay[nodeName]) {
+        element = document.createElement(nodeName);
+        document.body.appendChild(element);
+        display = getStyle(element, 'display');
+        element.parentNode.removeChild(element);
+        if (display === 'none') {
+            display = 'block';
+        }
+        elementDisplay[nodeName] = display;
+    }
+    return elementDisplay[nodeName];
+}
+/**
+ * 显示指定元素
+ * @returns {JQ}
+ */
+$.fn.show = function () {
+    return this.each(function () {
+        if (this.style.display === 'none') {
+            this.style.display = '';
+        }
+        if (getStyle(this, 'display') === 'none') {
+            this.style.display = defaultDisplay(this.nodeName);
+        }
+    });
+};
+
+/**
+ * 取得同辈元素的集合
+ * @param selector {String=}
+ * @returns {JQ}
+ */
+$.fn.siblings = function (selector) {
+    return this.prevAll(selector).add(this.nextAll(selector));
+};
+
+/**
+ * 切换元素的显示状态
+ */
+$.fn.toggle = function () {
+    return this.each(function () {
+        getStyle(this, 'display') === 'none' ? $(this).show() : $(this).hide();
+    });
+};
+
+$.fn.reflow = function () {
+    return this.each(function () {
+        return this.clientLeft;
+    });
+};
+
+$.fn.transition = function (duration) {
+    if (isNumber(duration)) {
+        duration = `${duration}ms`;
+    }
+    return this.each(function () {
+        this.style.webkitTransitionDuration = duration;
+        this.style.transitionDuration = duration;
+    });
+};
+
+$.fn.transitionEnd = function (callback) {
+    // eslint-disable-next-line @typescript-eslint/no-this-alias
+    const that = this;
+    const events = ['webkitTransitionEnd', 'transitionend'];
+    function fireCallback(e) {
+        if (e.target !== this) {
+            return;
+        }
+        // @ts-ignore
+        callback.call(this, e);
+        each(events, (_, event) => {
+            that.off(event, fireCallback);
+        });
+    }
+    each(events, (_, event) => {
+        that.on(event, fireCallback);
+    });
+    return this;
+};
+
+$.fn.transformOrigin = function (transformOrigin) {
+    return this.each(function () {
+        this.style.webkitTransformOrigin = transformOrigin;
+        this.style.transformOrigin = transformOrigin;
+    });
+};
+
+$.fn.transform = function (transform) {
+    return this.each(function () {
+        this.style.webkitTransform = transform;
+        this.style.transform = transform;
+    });
+};
+
+/**
+ * CSS 选择器和初始化函数组成的对象
+ */
+const entries = {};
+/**
+ * 注册并执行初始化函数
+ * @param selector CSS 选择器
+ * @param apiInit 初始化函数
+ * @param i 元素索引
+ * @param element 元素
+ */
+function mutation(selector, apiInit, i, element) {
+    let selectors = data(element, '_mdui_mutation');
+    if (!selectors) {
+        selectors = [];
+        data(element, '_mdui_mutation', selectors);
+    }
+    if (selectors.indexOf(selector) === -1) {
+        selectors.push(selector);
+        apiInit.call(element, i, element);
+    }
+}
+
+$.fn.mutation = function () {
+    return this.each((i, element) => {
+        const $this = $(element);
+        each(entries, (selector, apiInit) => {
+            if ($this.is(selector)) {
+                mutation(selector, apiInit, i, element);
+            }
+            $this.find(selector).each((i, element) => {
+                mutation(selector, apiInit, i, element);
+            });
+        });
+    });
+};
+
+$.showOverlay = function (zIndex) {
+    let $overlay = $('.mdui-overlay');
+    if ($overlay.length) {
+        $overlay.data('_overlay_is_deleted', false);
+        if (!isUndefined(zIndex)) {
+            $overlay.css('z-index', zIndex);
+        }
+    }
+    else {
+        if (isUndefined(zIndex)) {
+            zIndex = 2000;
+        }
+        $overlay = $('<div class="mdui-overlay">')
+            .appendTo(document.body)
+            .reflow()
+            .css('z-index', zIndex);
+    }
+    let level = $overlay.data('_overlay_level') || 0;
+    return $overlay.data('_overlay_level', ++level).addClass('mdui-overlay-show');
+};
+
+$.hideOverlay = function (force = false) {
+    const $overlay = $('.mdui-overlay');
+    if (!$overlay.length) {
+        return;
+    }
+    let level = force ? 1 : $overlay.data('_overlay_level');
+    if (level > 1) {
+        $overlay.data('_overlay_level', --level);
+        return;
+    }
+    $overlay
+        .data('_overlay_level', 0)
+        .removeClass('mdui-overlay-show')
+        .data('_overlay_is_deleted', true)
+        .transitionEnd(() => {
+        if ($overlay.data('_overlay_is_deleted')) {
+            $overlay.remove();
+        }
+    });
+};
+
+$.lockScreen = function () {
+    const $body = $('body');
+    // 不直接把 body 设为 box-sizing: border-box,避免污染全局样式
+    const newBodyWidth = $body.width();
+    let level = $body.data('_lockscreen_level') || 0;
+    $body
+        .addClass('mdui-locked')
+        .width(newBodyWidth)
+        .data('_lockscreen_level', ++level);
+};
+
+$.unlockScreen = function (force = false) {
+    const $body = $('body');
+    let level = force ? 1 : $body.data('_lockscreen_level');
+    if (level > 1) {
+        $body.data('_lockscreen_level', --level);
+        return;
+    }
+    $body.data('_lockscreen_level', 0).removeClass('mdui-locked').width('');
+};
+
+$.throttle = function (fn, delay = 16) {
+    let timer = null;
+    return function (...args) {
+        if (isNull(timer)) {
+            timer = setTimeout(() => {
+                fn.apply(this, args);
+                timer = null;
+            }, delay);
+        }
+    };
+};
+
+const GUID = {};
+$.guid = function (name) {
+    if (!isUndefined(name) && !isUndefined(GUID[name])) {
+        return GUID[name];
+    }
+    function s4() {
+        return Math.floor((1 + Math.random()) * 0x10000)
+            .toString(16)
+            .substring(1);
+    }
+    const guid = '_' +
+        s4() +
+        s4() +
+        '-' +
+        s4() +
+        '-' +
+        s4() +
+        '-' +
+        s4() +
+        '-' +
+        s4() +
+        s4() +
+        s4();
+    if (!isUndefined(name)) {
+        GUID[name] = guid;
+    }
+    return guid;
+};
+
+mdui.mutation = function (selector, apiInit) {
+    if (isUndefined(selector) || isUndefined(apiInit)) {
+        $(document).mutation();
+        return;
+    }
+    entries[selector] = apiInit;
+    $(selector).each((i, element) => mutation(selector, apiInit, i, element));
+};
+
+/**
+ * 触发组件上的事件
+ * @param eventName 事件名
+ * @param componentName 组件名
+ * @param target 在该元素上触发事件
+ * @param instance 组件实例
+ * @param parameters 事件参数
+ */
+function componentEvent(eventName, componentName, target, instance, parameters) {
+    if (!parameters) {
+        parameters = {};
+    }
+    // @ts-ignore
+    parameters.inst = instance;
+    const fullEventName = `${eventName}.mdui.${componentName}`;
+    // jQuery 事件
+    // @ts-ignore
+    if (typeof jQuery !== 'undefined') {
+        // @ts-ignore
+        jQuery(target).trigger(fullEventName, parameters);
+    }
+    const $target = $(target);
+    // mdui.jq 事件
+    $target.trigger(fullEventName, parameters);
+    const eventParams = {
+        bubbles: true,
+        cancelable: true,
+        detail: parameters,
+    };
+    const eventObject = new CustomEvent(fullEventName, eventParams);
+    // @ts-ignore
+    eventObject._detail = parameters;
+    $target[0].dispatchEvent(eventObject);
+}
+
+const $document = $(document);
+const $window = $(window);
+$('body');
+
+const DEFAULT_OPTIONS = {
+    tolerance: 5,
+    offset: 0,
+    initialClass: 'mdui-headroom',
+    pinnedClass: 'mdui-headroom-pinned-top',
+    unpinnedClass: 'mdui-headroom-unpinned-top',
+};
+class Headroom {
+    constructor(selector, options = {}) {
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS);
+        /**
+         * 当前 headroom 的状态
+         */
+        this.state = 'pinned';
+        /**
+         * 当前是否启用
+         */
+        this.isEnable = false;
+        /**
+         * 上次滚动后,垂直方向的距离
+         */
+        this.lastScrollY = 0;
+        /**
+         * AnimationFrame ID
+         */
+        this.rafId = 0;
+        this.$element = $(selector).first();
+        extend(this.options, options);
+        // tolerance 参数若为数值,转换为对象
+        const tolerance = this.options.tolerance;
+        if (isNumber(tolerance)) {
+            this.options.tolerance = {
+                down: tolerance,
+                up: tolerance,
+            };
+        }
+        this.enable();
+    }
+    /**
+     * 滚动时的处理
+     */
+    onScroll() {
+        this.rafId = window.requestAnimationFrame(() => {
+            const currentScrollY = window.pageYOffset;
+            const direction = currentScrollY > this.lastScrollY ? 'down' : 'up';
+            const tolerance = this.options.tolerance[direction];
+            const scrolled = Math.abs(currentScrollY - this.lastScrollY);
+            const toleranceExceeded = scrolled >= tolerance;
+            if (currentScrollY > this.lastScrollY &&
+                currentScrollY >= this.options.offset &&
+                toleranceExceeded) {
+                this.unpin();
+            }
+            else if ((currentScrollY < this.lastScrollY && toleranceExceeded) ||
+                currentScrollY <= this.options.offset) {
+                this.pin();
+            }
+            this.lastScrollY = currentScrollY;
+        });
+    }
+    /**
+     * 触发组件事件
+     * @param name
+     */
+    triggerEvent(name) {
+        componentEvent(name, 'headroom', this.$element, this);
+    }
+    /**
+     * 动画结束的回调
+     */
+    transitionEnd() {
+        if (this.state === 'pinning') {
+            this.state = 'pinned';
+            this.triggerEvent('pinned');
+        }
+        if (this.state === 'unpinning') {
+            this.state = 'unpinned';
+            this.triggerEvent('unpinned');
+        }
+    }
+    /**
+     * 使元素固定住
+     */
+    pin() {
+        if (this.state === 'pinning' ||
+            this.state === 'pinned' ||
+            !this.$element.hasClass(this.options.initialClass)) {
+            return;
+        }
+        this.triggerEvent('pin');
+        this.state = 'pinning';
+        this.$element
+            .removeClass(this.options.unpinnedClass)
+            .addClass(this.options.pinnedClass)
+            .transitionEnd(() => this.transitionEnd());
+    }
+    /**
+     * 使元素隐藏
+     */
+    unpin() {
+        if (this.state === 'unpinning' ||
+            this.state === 'unpinned' ||
+            !this.$element.hasClass(this.options.initialClass)) {
+            return;
+        }
+        this.triggerEvent('unpin');
+        this.state = 'unpinning';
+        this.$element
+            .removeClass(this.options.pinnedClass)
+            .addClass(this.options.unpinnedClass)
+            .transitionEnd(() => this.transitionEnd());
+    }
+    /**
+     * 启用 headroom 插件
+     */
+    enable() {
+        if (this.isEnable) {
+            return;
+        }
+        this.isEnable = true;
+        this.state = 'pinned';
+        this.$element
+            .addClass(this.options.initialClass)
+            .removeClass(this.options.pinnedClass)
+            .removeClass(this.options.unpinnedClass);
+        this.lastScrollY = window.pageYOffset;
+        $window.on('scroll', () => this.onScroll());
+    }
+    /**
+     * 禁用 headroom 插件
+     */
+    disable() {
+        if (!this.isEnable) {
+            return;
+        }
+        this.isEnable = false;
+        this.$element
+            .removeClass(this.options.initialClass)
+            .removeClass(this.options.pinnedClass)
+            .removeClass(this.options.unpinnedClass);
+        $window.off('scroll', () => this.onScroll());
+        window.cancelAnimationFrame(this.rafId);
+    }
+    /**
+     * 获取当前状态。共包含四种状态:`pinning`、`pinned`、`unpinning`、`unpinned`
+     */
+    getState() {
+        return this.state;
+    }
+}
+mdui.Headroom = Headroom;
+
+/**
+ * 解析 DATA API 参数
+ * @param element 元素
+ * @param name 属性名
+ */
+function parseOptions(element, name) {
+    const attr = $(element).attr(name);
+    if (!attr) {
+        return {};
+    }
+    return new Function('', `var json = ${attr}; return JSON.parse(JSON.stringify(json));`)();
+}
+
+const customAttr = 'mdui-headroom';
+$(() => {
+    mdui.mutation(`[${customAttr}]`, function () {
+        new mdui.Headroom(this, parseOptions(this, customAttr));
+    });
+});
+
+const DEFAULT_OPTIONS$1 = {
+    accordion: false,
+};
+class CollapseAbstract {
+    constructor(selector, options = {}) {
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS$1);
+        // CSS 类名
+        const classPrefix = `mdui-${this.getNamespace()}-item`;
+        this.classItem = classPrefix;
+        this.classItemOpen = `${classPrefix}-open`;
+        this.classHeader = `${classPrefix}-header`;
+        this.classBody = `${classPrefix}-body`;
+        this.$element = $(selector).first();
+        extend(this.options, options);
+        this.bindEvent();
+    }
+    /**
+     * 绑定事件
+     */
+    bindEvent() {
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        const that = this;
+        // 点击 header 时,打开/关闭 item
+        this.$element.on('click', `.${this.classHeader}`, function () {
+            const $header = $(this);
+            const $item = $header.parent();
+            const $items = that.getItems();
+            $items.each((_, item) => {
+                if ($item.is(item)) {
+                    that.toggle(item);
+                }
+            });
+        });
+        // 点击关闭按钮时,关闭 item
+        this.$element.on('click', `[mdui-${this.getNamespace()}-item-close]`, function () {
+            const $target = $(this);
+            const $item = $target.parents(`.${that.classItem}`).first();
+            that.close($item);
+        });
+    }
+    /**
+     * 指定 item 是否处于打开状态
+     * @param $item
+     */
+    isOpen($item) {
+        return $item.hasClass(this.classItemOpen);
+    }
+    /**
+     * 获取所有 item
+     */
+    getItems() {
+        return this.$element.children(`.${this.classItem}`);
+    }
+    /**
+     * 获取指定 item
+     * @param item
+     */
+    getItem(item) {
+        if (isNumber(item)) {
+            return this.getItems().eq(item);
+        }
+        return $(item).first();
+    }
+    /**
+     * 触发组件事件
+     * @param name 事件名
+     * @param $item 事件触发的目标 item
+     */
+    triggerEvent(name, $item) {
+        componentEvent(name, this.getNamespace(), $item, this);
+    }
+    /**
+     * 动画结束回调
+     * @param $content body 元素
+     * @param $item item 元素
+     */
+    transitionEnd($content, $item) {
+        if (this.isOpen($item)) {
+            $content.transition(0).height('auto').reflow().transition('');
+            this.triggerEvent('opened', $item);
+        }
+        else {
+            $content.height('');
+            this.triggerEvent('closed', $item);
+        }
+    }
+    /**
+     * 打开指定面板项
+     * @param item 面板项的索引号、或 CSS 选择器、或 DOM 元素、或 JQ 对象
+     */
+    open(item) {
+        const $item = this.getItem(item);
+        if (this.isOpen($item)) {
+            return;
+        }
+        // 关闭其他项
+        if (this.options.accordion) {
+            this.$element.children(`.${this.classItemOpen}`).each((_, element) => {
+                const $element = $(element);
+                if (!$element.is($item)) {
+                    this.close($element);
+                }
+            });
+        }
+        const $content = $item.children(`.${this.classBody}`);
+        $content
+            .height($content[0].scrollHeight)
+            .transitionEnd(() => this.transitionEnd($content, $item));
+        this.triggerEvent('open', $item);
+        $item.addClass(this.classItemOpen);
+    }
+    /**
+     * 关闭指定面板项
+     * @param item 面板项的索引号、或 CSS 选择器、或 DOM 元素、或 JQ 对象
+     */
+    close(item) {
+        const $item = this.getItem(item);
+        if (!this.isOpen($item)) {
+            return;
+        }
+        const $content = $item.children(`.${this.classBody}`);
+        this.triggerEvent('close', $item);
+        $item.removeClass(this.classItemOpen);
+        $content
+            .transition(0)
+            .height($content[0].scrollHeight)
+            .reflow()
+            .transition('')
+            .height('')
+            .transitionEnd(() => this.transitionEnd($content, $item));
+    }
+    /**
+     * 切换指定面板项的打开状态
+     * @param item 面板项的索引号、或 CSS 选择器、或 DOM 元素、或 JQ 对象
+     */
+    toggle(item) {
+        const $item = this.getItem(item);
+        this.isOpen($item) ? this.close($item) : this.open($item);
+    }
+    /**
+     * 打开所有面板项
+     */
+    openAll() {
+        this.getItems().each((_, element) => this.open(element));
+    }
+    /**
+     * 关闭所有面板项
+     */
+    closeAll() {
+        this.getItems().each((_, element) => this.close(element));
+    }
+}
+
+class Collapse extends CollapseAbstract {
+    getNamespace() {
+        return 'collapse';
+    }
+}
+mdui.Collapse = Collapse;
+
+const customAttr$1 = 'mdui-collapse';
+$(() => {
+    mdui.mutation(`[${customAttr$1}]`, function () {
+        new mdui.Collapse(this, parseOptions(this, customAttr$1));
+    });
+});
+
+class Panel extends CollapseAbstract {
+    getNamespace() {
+        return 'panel';
+    }
+}
+mdui.Panel = Panel;
+
+const customAttr$2 = 'mdui-panel';
+$(() => {
+    mdui.mutation(`[${customAttr$2}]`, function () {
+        new mdui.Panel(this, parseOptions(this, customAttr$2));
+    });
+});
+
+class Table {
+    constructor(selector) {
+        /**
+         * 表头 tr 元素
+         */
+        this.$thRow = $();
+        /**
+         * 表格 body 中的 tr 元素
+         */
+        this.$tdRows = $();
+        /**
+         * 表头的 checkbox 元素
+         */
+        this.$thCheckbox = $();
+        /**
+         * 表格 body 中的 checkbox 元素
+         */
+        this.$tdCheckboxs = $();
+        /**
+         * 表格行是否可选择
+         */
+        this.selectable = false;
+        /**
+         * 已选中的行数
+         */
+        this.selectedRow = 0;
+        this.$element = $(selector).first();
+        this.init();
+    }
+    /**
+     * 初始化表格
+     */
+    init() {
+        this.$thRow = this.$element.find('thead tr');
+        this.$tdRows = this.$element.find('tbody tr');
+        this.selectable = this.$element.hasClass('mdui-table-selectable');
+        this.updateThCheckbox();
+        this.updateTdCheckbox();
+        this.updateNumericCol();
+    }
+    /**
+     * 生成 checkbox 的 HTML 结构
+     * @param tag 标签名
+     */
+    createCheckboxHTML(tag) {
+        return (`<${tag} class="mdui-table-cell-checkbox">` +
+            '<label class="mdui-checkbox">' +
+            '<input type="checkbox"/>' +
+            '<i class="mdui-checkbox-icon"></i>' +
+            '</label>' +
+            `</${tag}>`);
+    }
+    /**
+     * 更新表头 checkbox 的状态
+     */
+    updateThCheckboxStatus() {
+        const checkbox = this.$thCheckbox[0];
+        const selectedRow = this.selectedRow;
+        const tdRowsLength = this.$tdRows.length;
+        checkbox.checked = selectedRow === tdRowsLength;
+        checkbox.indeterminate = !!selectedRow && selectedRow !== tdRowsLength;
+    }
+    /**
+     * 更新表格行的 checkbox
+     */
+    updateTdCheckbox() {
+        const rowSelectedClass = 'mdui-table-row-selected';
+        this.$tdRows.each((_, row) => {
+            const $row = $(row);
+            // 移除旧的 checkbox
+            $row.find('.mdui-table-cell-checkbox').remove();
+            if (!this.selectable) {
+                return;
+            }
+            // 创建 DOM
+            const $checkbox = $(this.createCheckboxHTML('td'))
+                .prependTo($row)
+                .find('input[type="checkbox"]');
+            // 默认选中的行
+            if ($row.hasClass(rowSelectedClass)) {
+                $checkbox[0].checked = true;
+                this.selectedRow++;
+            }
+            this.updateThCheckboxStatus();
+            // 绑定事件
+            $checkbox.on('change', () => {
+                if ($checkbox[0].checked) {
+                    $row.addClass(rowSelectedClass);
+                    this.selectedRow++;
+                }
+                else {
+                    $row.removeClass(rowSelectedClass);
+                    this.selectedRow--;
+                }
+                this.updateThCheckboxStatus();
+            });
+            this.$tdCheckboxs = this.$tdCheckboxs.add($checkbox);
+        });
+    }
+    /**
+     * 更新表头的 checkbox
+     */
+    updateThCheckbox() {
+        // 移除旧的 checkbox
+        this.$thRow.find('.mdui-table-cell-checkbox').remove();
+        if (!this.selectable) {
+            return;
+        }
+        this.$thCheckbox = $(this.createCheckboxHTML('th'))
+            .prependTo(this.$thRow)
+            .find('input[type="checkbox"]')
+            .on('change', () => {
+            const isCheckedAll = this.$thCheckbox[0].checked;
+            this.selectedRow = isCheckedAll ? this.$tdRows.length : 0;
+            this.$tdCheckboxs.each((_, checkbox) => {
+                checkbox.checked = isCheckedAll;
+            });
+            this.$tdRows.each((_, row) => {
+                isCheckedAll
+                    ? $(row).addClass('mdui-table-row-selected')
+                    : $(row).removeClass('mdui-table-row-selected');
+            });
+        });
+    }
+    /**
+     * 更新数值列
+     */
+    updateNumericCol() {
+        const numericClass = 'mdui-table-col-numeric';
+        this.$thRow.find('th').each((i, th) => {
+            const isNumericCol = $(th).hasClass(numericClass);
+            this.$tdRows.each((_, row) => {
+                const $td = $(row).find('td').eq(i);
+                isNumericCol
+                    ? $td.addClass(numericClass)
+                    : $td.removeClass(numericClass);
+            });
+        });
+    }
+}
+const dataName = '_mdui_table';
+$(() => {
+    mdui.mutation('.mdui-table', function () {
+        const $element = $(this);
+        if (!$element.data(dataName)) {
+            $element.data(dataName, new Table($element));
+        }
+    });
+});
+mdui.updateTables = function (selector) {
+    const $elements = isUndefined(selector) ? $('.mdui-table') : $(selector);
+    $elements.each((_, element) => {
+        const $element = $(element);
+        const instance = $element.data(dataName);
+        if (instance) {
+            instance.init();
+        }
+        else {
+            $element.data(dataName, new Table($element));
+        }
+    });
+};
+
+/**
+ * touch 事件后的 500ms 内禁用 mousedown 事件
+ *
+ * 不支持触控的屏幕上事件顺序为 mousedown -> mouseup -> click
+ * 支持触控的屏幕上事件顺序为 touchstart -> touchend -> mousedown -> mouseup -> click
+ *
+ * 在每一个事件中都使用 TouchHandler.isAllow(event) 判断事件是否可执行
+ * 在 touchstart 和 touchmove、touchend、touchcancel
+ *
+ * (function () {
+ *   $document
+ *     .on(start, function (e) {
+ *       if (!isAllow(e)) {
+ *         return;
+ *       }
+ *       register(e);
+ *       console.log(e.type);
+ *     })
+ *     .on(move, function (e) {
+ *       if (!isAllow(e)) {
+ *         return;
+ *       }
+ *       console.log(e.type);
+ *     })
+ *     .on(end, function (e) {
+ *       if (!isAllow(e)) {
+ *         return;
+ *       }
+ *       console.log(e.type);
+ *     })
+ *     .on(unlock, register);
+ * })();
+ */
+const startEvent = 'touchstart mousedown';
+const moveEvent = 'touchmove mousemove';
+const endEvent = 'touchend mouseup';
+const cancelEvent = 'touchcancel mouseleave';
+const unlockEvent = 'touchend touchmove touchcancel';
+let touches = 0;
+/**
+ * 该事件是否被允许,在执行事件前调用该方法判断事件是否可以执行
+ * 若已触发 touch 事件,则阻止之后的鼠标事件
+ * @param event
+ */
+function isAllow(event) {
+    return !(touches &&
+        [
+            'mousedown',
+            'mouseup',
+            'mousemove',
+            'click',
+            'mouseover',
+            'mouseout',
+            'mouseenter',
+            'mouseleave',
+        ].indexOf(event.type) > -1);
+}
+/**
+ * 在 touchstart 和 touchmove、touchend、touchcancel 事件中调用该方法注册事件
+ * @param event
+ */
+function register(event) {
+    if (event.type === 'touchstart') {
+        // 触发了 touch 事件
+        touches += 1;
+    }
+    else if (['touchmove', 'touchend', 'touchcancel'].indexOf(event.type) > -1) {
+        // touch 事件结束 500ms 后解除对鼠标事件的阻止
+        setTimeout(function () {
+            if (touches) {
+                touches -= 1;
+            }
+        }, 500);
+    }
+}
+
+/**
+ * Inspired by https://github.com/nolimits4web/Framework7/blob/master/src/js/fast-clicks.js
+ * https://github.com/nolimits4web/Framework7/blob/master/LICENSE
+ *
+ * Inspired by https://github.com/fians/Waves
+ */
+/**
+ * 显示涟漪动画
+ * @param event
+ * @param $ripple
+ */
+function show(event, $ripple) {
+    // 鼠标右键不产生涟漪
+    if (event instanceof MouseEvent && event.button === 2) {
+        return;
+    }
+    // 点击位置坐标
+    const touchPosition = typeof TouchEvent !== 'undefined' &&
+        event instanceof TouchEvent &&
+        event.touches.length
+        ? event.touches[0]
+        : event;
+    const touchStartX = touchPosition.pageX;
+    const touchStartY = touchPosition.pageY;
+    // 涟漪位置
+    const offset = $ripple.offset();
+    const height = $ripple.innerHeight();
+    const width = $ripple.innerWidth();
+    const center = {
+        x: touchStartX - offset.left,
+        y: touchStartY - offset.top,
+    };
+    const diameter = Math.max(Math.pow(Math.pow(height, 2) + Math.pow(width, 2), 0.5), 48);
+    // 涟漪扩散动画
+    const translate = `translate3d(${-center.x + width / 2}px,` +
+        `${-center.y + height / 2}px, 0) scale(1)`;
+    // 涟漪的 DOM 结构,并缓存动画效果
+    $(`<div class="mdui-ripple-wave" ` +
+        `style="width:${diameter}px;height:${diameter}px;` +
+        `margin-top:-${diameter / 2}px;margin-left:-${diameter / 2}px;` +
+        `left:${center.x}px;top:${center.y}px;"></div>`)
+        .data('_ripple_wave_translate', translate)
+        .prependTo($ripple)
+        .reflow()
+        .transform(translate);
+}
+/**
+ * 隐藏并移除涟漪
+ * @param $wave
+ */
+function removeRipple($wave) {
+    if (!$wave.length || $wave.data('_ripple_wave_removed')) {
+        return;
+    }
+    $wave.data('_ripple_wave_removed', true);
+    let removeTimer = setTimeout(() => $wave.remove(), 400);
+    const translate = $wave.data('_ripple_wave_translate');
+    $wave
+        .addClass('mdui-ripple-wave-fill')
+        .transform(translate.replace('scale(1)', 'scale(1.01)'))
+        .transitionEnd(() => {
+        clearTimeout(removeTimer);
+        $wave
+            .addClass('mdui-ripple-wave-out')
+            .transform(translate.replace('scale(1)', 'scale(1.01)'));
+        removeTimer = setTimeout(() => $wave.remove(), 700);
+        setTimeout(() => {
+            $wave.transitionEnd(() => {
+                clearTimeout(removeTimer);
+                $wave.remove();
+            });
+        }, 0);
+    });
+}
+/**
+ * 隐藏涟漪动画
+ * @param this
+ */
+function hide() {
+    const $ripple = $(this);
+    $ripple.children('.mdui-ripple-wave').each((_, wave) => {
+        removeRipple($(wave));
+    });
+    $ripple.off(`${moveEvent} ${endEvent} ${cancelEvent}`, hide);
+}
+/**
+ * 显示涟漪,并绑定 touchend 等事件
+ * @param event
+ */
+function showRipple(event) {
+    if (!isAllow(event)) {
+        return;
+    }
+    register(event);
+    // Chrome 59 点击滚动条时,会在 document 上触发事件
+    if (event.target === document) {
+        return;
+    }
+    const $target = $(event.target);
+    // 获取含 .mdui-ripple 类的元素
+    const $ripple = $target.hasClass('mdui-ripple')
+        ? $target
+        : $target.parents('.mdui-ripple').first();
+    if (!$ripple.length) {
+        return;
+    }
+    // 禁用状态的元素上不产生涟漪效果
+    if ($ripple.prop('disabled') || !isUndefined($ripple.attr('disabled'))) {
+        return;
+    }
+    if (event.type === 'touchstart') {
+        let hidden = false;
+        // touchstart 触发指定时间后开始涟漪动画,避免手指滑动时也触发涟漪
+        let timer = setTimeout(() => {
+            timer = 0;
+            show(event, $ripple);
+        }, 200);
+        const hideRipple = () => {
+            // 如果手指没有移动,且涟漪动画还没有开始,则开始涟漪动画
+            if (timer) {
+                clearTimeout(timer);
+                timer = 0;
+                show(event, $ripple);
+            }
+            if (!hidden) {
+                hidden = true;
+                hide.call($ripple);
+            }
+        };
+        // 手指移动后,移除涟漪动画
+        const touchMove = () => {
+            if (timer) {
+                clearTimeout(timer);
+                timer = 0;
+            }
+            hideRipple();
+        };
+        $ripple.on('touchmove', touchMove).on('touchend touchcancel', hideRipple);
+    }
+    else {
+        show(event, $ripple);
+        $ripple.on(`${moveEvent} ${endEvent} ${cancelEvent}`, hide);
+    }
+}
+$(() => {
+    $document.on(startEvent, showRipple).on(unlockEvent, register);
+});
+
+const defaultData = {
+    reInit: false,
+    domLoadedEvent: false,
+};
+/**
+ * 输入框事件
+ * @param event
+ * @param data
+ */
+function inputEvent(event, data = {}) {
+    data = extend({}, defaultData, data);
+    const input = event.target;
+    const $input = $(input);
+    const eventType = event.type;
+    const value = $input.val();
+    // 文本框类型
+    const inputType = $input.attr('type') || '';
+    if (['checkbox', 'button', 'submit', 'range', 'radio', 'image'].indexOf(inputType) > -1) {
+        return;
+    }
+    const $textfield = $input.parent('.mdui-textfield');
+    // 输入框是否聚焦
+    if (eventType === 'focus') {
+        $textfield.addClass('mdui-textfield-focus');
+    }
+    if (eventType === 'blur') {
+        $textfield.removeClass('mdui-textfield-focus');
+    }
+    // 输入框是否为空
+    if (eventType === 'blur' || eventType === 'input') {
+        value
+            ? $textfield.addClass('mdui-textfield-not-empty')
+            : $textfield.removeClass('mdui-textfield-not-empty');
+    }
+    // 输入框是否禁用
+    input.disabled
+        ? $textfield.addClass('mdui-textfield-disabled')
+        : $textfield.removeClass('mdui-textfield-disabled');
+    // 表单验证
+    if ((eventType === 'input' || eventType === 'blur') &&
+        !data.domLoadedEvent &&
+        input.validity) {
+        input.validity.valid
+            ? $textfield.removeClass('mdui-textfield-invalid-html5')
+            : $textfield.addClass('mdui-textfield-invalid-html5');
+    }
+    // textarea 高度自动调整
+    if ($input.is('textarea')) {
+        // IE bug:textarea 的值仅为多个换行,不含其他内容时,textarea 的高度不准确
+        //         此时,在计算高度前,在值的开头加入一个空格,计算完后,移除空格
+        const inputValue = value;
+        let hasExtraSpace = false;
+        if (inputValue.replace(/[\r\n]/g, '') === '') {
+            $input.val(' ' + inputValue);
+            hasExtraSpace = true;
+        }
+        // 设置 textarea 高度
+        $input.outerHeight('');
+        const height = $input.outerHeight();
+        const scrollHeight = input.scrollHeight;
+        if (scrollHeight > height) {
+            $input.outerHeight(scrollHeight);
+        }
+        // 计算完,还原 textarea 的值
+        if (hasExtraSpace) {
+            $input.val(inputValue);
+        }
+    }
+    // 实时字数统计
+    if (data.reInit) {
+        $textfield.find('.mdui-textfield-counter').remove();
+    }
+    const maxLength = $input.attr('maxlength');
+    if (maxLength) {
+        if (data.reInit || data.domLoadedEvent) {
+            $('<div class="mdui-textfield-counter">' +
+                `<span class="mdui-textfield-counter-inputed"></span> / ${maxLength}` +
+                '</div>').appendTo($textfield);
+        }
+        $textfield
+            .find('.mdui-textfield-counter-inputed')
+            .text(value.length.toString());
+    }
+    // 含 帮助文本、错误提示、字数统计 时,增加文本框底部内边距
+    if ($textfield.find('.mdui-textfield-helper').length ||
+        $textfield.find('.mdui-textfield-error').length ||
+        maxLength) {
+        $textfield.addClass('mdui-textfield-has-bottom');
+    }
+}
+$(() => {
+    // 绑定事件
+    $document.on('input focus blur', '.mdui-textfield-input', { useCapture: true }, inputEvent);
+    // 可展开文本框展开
+    $document.on('click', '.mdui-textfield-expandable .mdui-textfield-icon', function () {
+        $(this)
+            .parents('.mdui-textfield')
+            .addClass('mdui-textfield-expanded')
+            .find('.mdui-textfield-input')[0]
+            .focus();
+    });
+    // 可展开文本框关闭
+    $document.on('click', '.mdui-textfield-expanded .mdui-textfield-close', function () {
+        $(this)
+            .parents('.mdui-textfield')
+            .removeClass('mdui-textfield-expanded')
+            .find('.mdui-textfield-input')
+            .val('');
+    });
+    /**
+     * 初始化文本框
+     */
+    mdui.mutation('.mdui-textfield', function () {
+        $(this).find('.mdui-textfield-input').trigger('input', {
+            domLoadedEvent: true,
+        });
+    });
+});
+mdui.updateTextFields = function (selector) {
+    const $elements = isUndefined(selector) ? $('.mdui-textfield') : $(selector);
+    $elements.each((_, element) => {
+        $(element).find('.mdui-textfield-input').trigger('input', {
+            reInit: true,
+        });
+    });
+};
+
+/**
+ * 滑块的值改变后修改滑块样式
+ * @param $slider
+ */
+function updateValueStyle($slider) {
+    const data = $slider.data();
+    const $track = data._slider_$track;
+    const $fill = data._slider_$fill;
+    const $thumb = data._slider_$thumb;
+    const $input = data._slider_$input;
+    const min = data._slider_min;
+    const max = data._slider_max;
+    const isDisabled = data._slider_disabled;
+    const isDiscrete = data._slider_discrete;
+    const $thumbText = data._slider_$thumbText;
+    const value = $input.val();
+    const percent = ((value - min) / (max - min)) * 100;
+    $fill.width(`${percent}%`);
+    $track.width(`${100 - percent}%`);
+    if (isDisabled) {
+        $fill.css('padding-right', '6px');
+        $track.css('padding-left', '6px');
+    }
+    $thumb.css('left', `${percent}%`);
+    if (isDiscrete) {
+        $thumbText.text(value);
+    }
+    percent === 0
+        ? $slider.addClass('mdui-slider-zero')
+        : $slider.removeClass('mdui-slider-zero');
+}
+/**
+ * 重新初始化滑块
+ * @param $slider
+ */
+function reInit($slider) {
+    const $track = $('<div class="mdui-slider-track"></div>');
+    const $fill = $('<div class="mdui-slider-fill"></div>');
+    const $thumb = $('<div class="mdui-slider-thumb"></div>');
+    const $input = $slider.find('input[type="range"]');
+    const isDisabled = $input[0].disabled;
+    const isDiscrete = $slider.hasClass('mdui-slider-discrete');
+    // 禁用状态
+    isDisabled
+        ? $slider.addClass('mdui-slider-disabled')
+        : $slider.removeClass('mdui-slider-disabled');
+    // 重新填充 HTML
+    $slider.find('.mdui-slider-track').remove();
+    $slider.find('.mdui-slider-fill').remove();
+    $slider.find('.mdui-slider-thumb').remove();
+    $slider.append($track).append($fill).append($thumb);
+    // 间续型滑块
+    let $thumbText = $();
+    if (isDiscrete) {
+        $thumbText = $('<span></span>');
+        $thumb.empty().append($thumbText);
+    }
+    $slider.data('_slider_$track', $track);
+    $slider.data('_slider_$fill', $fill);
+    $slider.data('_slider_$thumb', $thumb);
+    $slider.data('_slider_$input', $input);
+    $slider.data('_slider_min', $input.attr('min'));
+    $slider.data('_slider_max', $input.attr('max'));
+    $slider.data('_slider_disabled', isDisabled);
+    $slider.data('_slider_discrete', isDiscrete);
+    $slider.data('_slider_$thumbText', $thumbText);
+    // 设置默认值
+    updateValueStyle($slider);
+}
+const rangeSelector = '.mdui-slider input[type="range"]';
+$(() => {
+    // 滑块滑动事件
+    $document.on('input change', rangeSelector, function () {
+        const $slider = $(this).parent();
+        updateValueStyle($slider);
+    });
+    // 开始触摸滑块事件
+    $document.on(startEvent, rangeSelector, function (event) {
+        if (!isAllow(event)) {
+            return;
+        }
+        register(event);
+        if (this.disabled) {
+            return;
+        }
+        const $slider = $(this).parent();
+        $slider.addClass('mdui-slider-focus');
+    });
+    // 结束触摸滑块事件
+    $document.on(endEvent, rangeSelector, function (event) {
+        if (!isAllow(event)) {
+            return;
+        }
+        if (this.disabled) {
+            return;
+        }
+        const $slider = $(this).parent();
+        $slider.removeClass('mdui-slider-focus');
+    });
+    $document.on(unlockEvent, rangeSelector, register);
+    /**
+     * 初始化滑块
+     */
+    mdui.mutation('.mdui-slider', function () {
+        reInit($(this));
+    });
+});
+mdui.updateSliders = function (selector) {
+    const $elements = isUndefined(selector) ? $('.mdui-slider') : $(selector);
+    $elements.each((_, element) => {
+        reInit($(element));
+    });
+};
+
+const DEFAULT_OPTIONS$2 = {
+    trigger: 'hover',
+};
+class Fab {
+    constructor(selector, options = {}) {
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS$2);
+        /**
+         * 当前 fab 的状态
+         */
+        this.state = 'closed';
+        this.$element = $(selector).first();
+        extend(this.options, options);
+        this.$btn = this.$element.find('.mdui-fab');
+        this.$dial = this.$element.find('.mdui-fab-dial');
+        this.$dialBtns = this.$dial.find('.mdui-fab');
+        if (this.options.trigger === 'hover') {
+            this.$btn.on('touchstart mouseenter', () => this.open());
+            this.$element.on('mouseleave', () => this.close());
+        }
+        if (this.options.trigger === 'click') {
+            this.$btn.on(startEvent, () => this.open());
+        }
+        // 触摸屏幕其他地方关闭快速拨号
+        $document.on(startEvent, (event) => {
+            if ($(event.target).parents('.mdui-fab-wrapper').length) {
+                return;
+            }
+            this.close();
+        });
+    }
+    /**
+     * 触发组件事件
+     * @param name
+     */
+    triggerEvent(name) {
+        componentEvent(name, 'fab', this.$element, this);
+    }
+    /**
+     * 当前是否为打开状态
+     */
+    isOpen() {
+        return this.state === 'opening' || this.state === 'opened';
+    }
+    /**
+     * 打开快速拨号菜单
+     */
+    open() {
+        if (this.isOpen()) {
+            return;
+        }
+        // 为菜单中的按钮添加不同的 transition-delay
+        this.$dialBtns.each((index, btn) => {
+            const delay = `${15 * (this.$dialBtns.length - index)}ms`;
+            btn.style.transitionDelay = delay;
+            btn.style.webkitTransitionDelay = delay;
+        });
+        this.$dial.css('height', 'auto').addClass('mdui-fab-dial-show');
+        // 如果按钮中存在 .mdui-fab-opened 的图标,则进行图标切换
+        if (this.$btn.find('.mdui-fab-opened').length) {
+            this.$btn.addClass('mdui-fab-opened');
+        }
+        this.state = 'opening';
+        this.triggerEvent('open');
+        // 打开顺序为从下到上逐个打开,最上面的打开后才表示动画完成
+        this.$dialBtns.first().transitionEnd(() => {
+            if (this.$btn.hasClass('mdui-fab-opened')) {
+                this.state = 'opened';
+                this.triggerEvent('opened');
+            }
+        });
+    }
+    /**
+     * 关闭快速拨号菜单
+     */
+    close() {
+        if (!this.isOpen()) {
+            return;
+        }
+        // 为菜单中的按钮添加不同的 transition-delay
+        this.$dialBtns.each((index, btn) => {
+            const delay = `${15 * index}ms`;
+            btn.style.transitionDelay = delay;
+            btn.style.webkitTransitionDelay = delay;
+        });
+        this.$dial.removeClass('mdui-fab-dial-show');
+        this.$btn.removeClass('mdui-fab-opened');
+        this.state = 'closing';
+        this.triggerEvent('close');
+        // 从上往下依次关闭,最后一个关闭后才表示动画完成
+        this.$dialBtns.last().transitionEnd(() => {
+            if (this.$btn.hasClass('mdui-fab-opened')) {
+                return;
+            }
+            this.state = 'closed';
+            this.triggerEvent('closed');
+            this.$dial.css('height', 0);
+        });
+    }
+    /**
+     * 切换快速拨号菜单的打开状态
+     */
+    toggle() {
+        this.isOpen() ? this.close() : this.open();
+    }
+    /**
+     * 以动画的形式显示整个浮动操作按钮
+     */
+    show() {
+        this.$element.removeClass('mdui-fab-hide');
+    }
+    /**
+     * 以动画的形式隐藏整个浮动操作按钮
+     */
+    hide() {
+        this.$element.addClass('mdui-fab-hide');
+    }
+    /**
+     * 返回当前快速拨号菜单的打开状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+     */
+    getState() {
+        return this.state;
+    }
+}
+mdui.Fab = Fab;
+
+const customAttr$3 = 'mdui-fab';
+$(() => {
+    // mouseenter 不冒泡,无法进行事件委托,这里用 mouseover 代替。
+    // 不管是 click 、 mouseover 还是 touchstart ,都先初始化。
+    $document.on('touchstart mousedown mouseover', `[${customAttr$3}]`, function () {
+        new mdui.Fab(this, parseOptions(this, customAttr$3));
+    });
+});
+
+/**
+ * 最终生成的元素结构为:
+ *  <select class="mdui-select" mdui-select="{position: 'top'}" style="display: none;"> // $native
+ *    <option value="1">State 1</option>
+ *    <option value="2">State 2</option>
+ *    <option value="3" disabled="">State 3</option>
+ *  </select>
+ *  <div class="mdui-select mdui-select-position-top" style="" id="88dec0e4-d4a2-c6d0-0e7f-1ba4501e0553"> // $element
+ *    <span class="mdui-select-selected">State 1</span> // $selected
+ *    <div class="mdui-select-menu" style="transform-origin: center 100% 0px;"> // $menu
+ *      <div class="mdui-select-menu-item mdui-ripple" selected="">State 1</div> // $items
+ *      <div class="mdui-select-menu-item mdui-ripple">State 2</div>
+ *      <div class="mdui-select-menu-item mdui-ripple" disabled="">State 3</div>
+ *    </div>
+ *  </div>
+ */
+const DEFAULT_OPTIONS$3 = {
+    position: 'auto',
+    gutter: 16,
+};
+class Select {
+    constructor(selector, options = {}) {
+        /**
+         * 生成的 `<div class="mdui-select">` 元素的 JQ 对象
+         */
+        this.$element = $();
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS$3);
+        /**
+         * select 的 size 属性的值,根据该值设置 select 的高度
+         */
+        this.size = 0;
+        /**
+         * 占位元素,显示已选中菜单项的文本
+         */
+        this.$selected = $();
+        /**
+         * 菜单项的外层元素的 JQ 对象
+         */
+        this.$menu = $();
+        /**
+         * 菜单项数组的 JQ 对象
+         */
+        this.$items = $();
+        /**
+         * 当前选中的菜单项的索引号
+         */
+        this.selectedIndex = 0;
+        /**
+         * 当前选中菜单项的文本
+         */
+        this.selectedText = '';
+        /**
+         * 当前选中菜单项的值
+         */
+        this.selectedValue = '';
+        /**
+         * 当前 select 的状态
+         */
+        this.state = 'closed';
+        this.$native = $(selector).first();
+        this.$native.hide();
+        extend(this.options, options);
+        // 为当前 select 生成唯一 ID
+        this.uniqueID = $.guid();
+        // 生成 select
+        this.handleUpdate();
+        // 点击 select 外面区域关闭
+        $document.on('click touchstart', (event) => {
+            const $target = $(event.target);
+            if (this.isOpen() &&
+                !$target.is(this.$element) &&
+                !contains(this.$element[0], $target[0])) {
+                this.close();
+            }
+        });
+    }
+    /**
+     * 调整菜单位置
+     */
+    readjustMenu() {
+        const windowHeight = $window.height();
+        // mdui-select 高度
+        const elementHeight = this.$element.height();
+        // 菜单项高度
+        const $itemFirst = this.$items.first();
+        const itemHeight = $itemFirst.height();
+        const itemMargin = parseInt($itemFirst.css('margin-top'));
+        // 菜单高度
+        const menuWidth = this.$element.innerWidth() + 0.01; // 必须比真实宽度多一点,不然会出现省略号
+        let menuHeight = itemHeight * this.size + itemMargin * 2;
+        // mdui-select 在窗口中的位置
+        const elementTop = this.$element[0].getBoundingClientRect().top;
+        let transformOriginY;
+        let menuMarginTop;
+        if (this.options.position === 'bottom') {
+            menuMarginTop = elementHeight;
+            transformOriginY = '0px';
+        }
+        else if (this.options.position === 'top') {
+            menuMarginTop = -menuHeight - 1;
+            transformOriginY = '100%';
+        }
+        else {
+            // 菜单高度不能超过窗口高度
+            const menuMaxHeight = windowHeight - this.options.gutter * 2;
+            if (menuHeight > menuMaxHeight) {
+                menuHeight = menuMaxHeight;
+            }
+            // 菜单的 margin-top
+            menuMarginTop = -(itemMargin +
+                this.selectedIndex * itemHeight +
+                (itemHeight - elementHeight) / 2);
+            const menuMaxMarginTop = -(itemMargin +
+                (this.size - 1) * itemHeight +
+                (itemHeight - elementHeight) / 2);
+            if (menuMarginTop < menuMaxMarginTop) {
+                menuMarginTop = menuMaxMarginTop;
+            }
+            // 菜单不能超出窗口
+            const menuTop = elementTop + menuMarginTop;
+            if (menuTop < this.options.gutter) {
+                // 不能超出窗口上方
+                menuMarginTop = -(elementTop - this.options.gutter);
+            }
+            else if (menuTop + menuHeight + this.options.gutter > windowHeight) {
+                // 不能超出窗口下方
+                menuMarginTop = -(elementTop +
+                    menuHeight +
+                    this.options.gutter -
+                    windowHeight);
+            }
+            // transform 的 Y 轴坐标
+            transformOriginY = `${this.selectedIndex * itemHeight + itemHeight / 2 + itemMargin}px`;
+        }
+        // 设置样式
+        this.$element.innerWidth(menuWidth);
+        this.$menu
+            .innerWidth(menuWidth)
+            .height(menuHeight)
+            .css({
+            'margin-top': menuMarginTop + 'px',
+            'transform-origin': 'center ' + transformOriginY + ' 0',
+        });
+    }
+    /**
+     * select 是否为打开状态
+     */
+    isOpen() {
+        return this.state === 'opening' || this.state === 'opened';
+    }
+    /**
+     * 对原生 select 组件进行了修改后,需要调用该方法
+     */
+    handleUpdate() {
+        if (this.isOpen()) {
+            this.close();
+        }
+        this.selectedValue = this.$native.val();
+        const itemsData = [];
+        this.$items = $();
+        // 生成 HTML
+        this.$native.find('option').each((index, option) => {
+            const text = option.textContent || '';
+            const value = option.value;
+            const disabled = option.disabled;
+            const selected = this.selectedValue === value;
+            itemsData.push({
+                value,
+                text,
+                disabled,
+                selected,
+                index,
+            });
+            if (selected) {
+                this.selectedText = text;
+                this.selectedIndex = index;
+            }
+            this.$items = this.$items.add('<div class="mdui-select-menu-item mdui-ripple"' +
+                (disabled ? ' disabled' : '') +
+                (selected ? ' selected' : '') +
+                `>${text}</div>`);
+        });
+        this.$selected = $(`<span class="mdui-select-selected">${this.selectedText}</span>`);
+        this.$element = $(`<div class="mdui-select mdui-select-position-${this.options.position}" ` +
+            `style="${this.$native.attr('style')}" ` +
+            `id="${this.uniqueID}"></div>`)
+            .show()
+            .append(this.$selected);
+        this.$menu = $('<div class="mdui-select-menu"></div>')
+            .appendTo(this.$element)
+            .append(this.$items);
+        $(`#${this.uniqueID}`).remove();
+        this.$native.after(this.$element);
+        // 根据 select 的 size 属性设置高度
+        this.size = parseInt(this.$native.attr('size') || '0');
+        if (this.size <= 0) {
+            this.size = this.$items.length;
+            if (this.size > 8) {
+                this.size = 8;
+            }
+        }
+        // 点击选项时关闭下拉菜单
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        const that = this;
+        this.$items.on('click', function () {
+            if (that.state === 'closing') {
+                return;
+            }
+            const $item = $(this);
+            const index = $item.index();
+            const data = itemsData[index];
+            if (data.disabled) {
+                return;
+            }
+            that.$selected.text(data.text);
+            that.$native.val(data.value);
+            that.$items.removeAttr('selected');
+            $item.attr('selected', '');
+            that.selectedIndex = data.index;
+            that.selectedValue = data.value;
+            that.selectedText = data.text;
+            that.$native.trigger('change');
+            that.close();
+        });
+        // 点击 $element 时打开下拉菜单
+        this.$element.on('click', (event) => {
+            const $target = $(event.target);
+            // 在菜单上点击时不打开
+            if ($target.is('.mdui-select-menu') ||
+                $target.is('.mdui-select-menu-item')) {
+                return;
+            }
+            this.toggle();
+        });
+    }
+    /**
+     * 动画结束的回调
+     */
+    transitionEnd() {
+        this.$element.removeClass('mdui-select-closing');
+        if (this.state === 'opening') {
+            this.state = 'opened';
+            this.triggerEvent('opened');
+            this.$menu.css('overflow-y', 'auto');
+        }
+        if (this.state === 'closing') {
+            this.state = 'closed';
+            this.triggerEvent('closed');
+            // 恢复样式
+            this.$element.innerWidth('');
+            this.$menu.css({
+                'margin-top': '',
+                height: '',
+                width: '',
+            });
+        }
+    }
+    /**
+     * 触发组件事件
+     * @param name
+     */
+    triggerEvent(name) {
+        componentEvent(name, 'select', this.$native, this);
+    }
+    /**
+     * 切换下拉菜单的打开状态
+     */
+    toggle() {
+        this.isOpen() ? this.close() : this.open();
+    }
+    /**
+     * 打开下拉菜单
+     */
+    open() {
+        if (this.isOpen()) {
+            return;
+        }
+        this.state = 'opening';
+        this.triggerEvent('open');
+        this.readjustMenu();
+        this.$element.addClass('mdui-select-open');
+        this.$menu.transitionEnd(() => this.transitionEnd());
+    }
+    /**
+     * 关闭下拉菜单
+     */
+    close() {
+        if (!this.isOpen()) {
+            return;
+        }
+        this.state = 'closing';
+        this.triggerEvent('close');
+        this.$menu.css('overflow-y', '');
+        this.$element
+            .removeClass('mdui-select-open')
+            .addClass('mdui-select-closing');
+        this.$menu.transitionEnd(() => this.transitionEnd());
+    }
+    /**
+     * 获取当前菜单的状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+     */
+    getState() {
+        return this.state;
+    }
+}
+mdui.Select = Select;
+
+const customAttr$4 = 'mdui-select';
+$(() => {
+    mdui.mutation(`[${customAttr$4}]`, function () {
+        new mdui.Select(this, parseOptions(this, customAttr$4));
+    });
+});
+
+$(() => {
+    // 滚动时隐藏应用栏
+    mdui.mutation('.mdui-appbar-scroll-hide', function () {
+        new mdui.Headroom(this);
+    });
+    // 滚动时只隐藏应用栏中的工具栏
+    mdui.mutation('.mdui-appbar-scroll-toolbar-hide', function () {
+        new mdui.Headroom(this, {
+            pinnedClass: 'mdui-headroom-pinned-toolbar',
+            unpinnedClass: 'mdui-headroom-unpinned-toolbar',
+        });
+    });
+});
+
+const DEFAULT_OPTIONS$4 = {
+    trigger: 'click',
+    loop: false,
+};
+class Tab {
+    constructor(selector, options = {}) {
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS$4);
+        /**
+         * 当前激活的 tab 的索引号。为 -1 时表示没有激活的选项卡,或不存在选项卡
+         */
+        this.activeIndex = -1;
+        this.$element = $(selector).first();
+        extend(this.options, options);
+        this.$tabs = this.$element.children('a');
+        this.$indicator = $('<div class="mdui-tab-indicator"></div>').appendTo(this.$element);
+        // 根据 url hash 获取默认激活的选项卡
+        const hash = window.location.hash;
+        if (hash) {
+            this.$tabs.each((index, tab) => {
+                if ($(tab).attr('href') === hash) {
+                    this.activeIndex = index;
+                    return false;
+                }
+                return true;
+            });
+        }
+        // 含 .mdui-tab-active 的元素默认激活
+        if (this.activeIndex === -1) {
+            this.$tabs.each((index, tab) => {
+                if ($(tab).hasClass('mdui-tab-active')) {
+                    this.activeIndex = index;
+                    return false;
+                }
+                return true;
+            });
+        }
+        // 存在选项卡时,默认激活第一个选项卡
+        if (this.$tabs.length && this.activeIndex === -1) {
+            this.activeIndex = 0;
+        }
+        // 设置激活状态选项卡
+        this.setActive();
+        // 监听窗口大小变化事件,调整指示器位置
+        $window.on('resize', $.throttle(() => this.setIndicatorPosition(), 100));
+        // 监听点击选项卡事件
+        this.$tabs.each((_, tab) => {
+            this.bindTabEvent(tab);
+        });
+    }
+    /**
+     * 指定选项卡是否已禁用
+     * @param $tab
+     */
+    isDisabled($tab) {
+        return $tab.attr('disabled') !== undefined;
+    }
+    /**
+     * 绑定在 Tab 上点击或悬浮的事件
+     * @param tab
+     */
+    bindTabEvent(tab) {
+        const $tab = $(tab);
+        // 点击或鼠标移入触发的事件
+        const clickEvent = () => {
+            // 禁用状态的选项卡无法选中
+            if (this.isDisabled($tab)) {
+                return false;
+            }
+            this.activeIndex = this.$tabs.index(tab);
+            this.setActive();
+        };
+        // 无论 trigger 是 click 还是 hover,都会响应 click 事件
+        $tab.on('click', clickEvent);
+        // trigger 为 hover 时,额外响应 mouseenter 事件
+        if (this.options.trigger === 'hover') {
+            $tab.on('mouseenter', clickEvent);
+        }
+        // 阻止链接的默认点击动作
+        $tab.on('click', () => {
+            if (($tab.attr('href') || '').indexOf('#') === 0) {
+                return false;
+            }
+        });
+    }
+    /**
+     * 触发组件事件
+     * @param name
+     * @param $element
+     * @param parameters
+     */
+    triggerEvent(name, $element, parameters = {}) {
+        componentEvent(name, 'tab', $element, this, parameters);
+    }
+    /**
+     * 设置激活状态的选项卡
+     */
+    setActive() {
+        this.$tabs.each((index, tab) => {
+            const $tab = $(tab);
+            const targetId = $tab.attr('href') || '';
+            // 设置选项卡激活状态
+            if (index === this.activeIndex && !this.isDisabled($tab)) {
+                if (!$tab.hasClass('mdui-tab-active')) {
+                    this.triggerEvent('change', this.$element, {
+                        index: this.activeIndex,
+                        id: targetId.substr(1),
+                    });
+                    this.triggerEvent('show', $tab);
+                    $tab.addClass('mdui-tab-active');
+                }
+                $(targetId).show();
+                this.setIndicatorPosition();
+            }
+            else {
+                $tab.removeClass('mdui-tab-active');
+                $(targetId).hide();
+            }
+        });
+    }
+    /**
+     * 设置选项卡指示器的位置
+     */
+    setIndicatorPosition() {
+        // 选项卡数量为 0 时,不显示指示器
+        if (this.activeIndex === -1) {
+            this.$indicator.css({
+                left: 0,
+                width: 0,
+            });
+            return;
+        }
+        const $activeTab = this.$tabs.eq(this.activeIndex);
+        if (this.isDisabled($activeTab)) {
+            return;
+        }
+        const activeTabOffset = $activeTab.offset();
+        this.$indicator.css({
+            left: `${activeTabOffset.left +
+                this.$element[0].scrollLeft -
+                this.$element[0].getBoundingClientRect().left}px`,
+            width: `${$activeTab.innerWidth()}px`,
+        });
+    }
+    /**
+     * 切换到下一个选项卡
+     */
+    next() {
+        if (this.activeIndex === -1) {
+            return;
+        }
+        if (this.$tabs.length > this.activeIndex + 1) {
+            this.activeIndex++;
+        }
+        else if (this.options.loop) {
+            this.activeIndex = 0;
+        }
+        this.setActive();
+    }
+    /**
+     * 切换到上一个选项卡
+     */
+    prev() {
+        if (this.activeIndex === -1) {
+            return;
+        }
+        if (this.activeIndex > 0) {
+            this.activeIndex--;
+        }
+        else if (this.options.loop) {
+            this.activeIndex = this.$tabs.length - 1;
+        }
+        this.setActive();
+    }
+    /**
+     * 显示指定索引号、或指定id的选项卡
+     * @param index 索引号、或id
+     */
+    show(index) {
+        if (this.activeIndex === -1) {
+            return;
+        }
+        if (isNumber(index)) {
+            this.activeIndex = index;
+        }
+        else {
+            this.$tabs.each((i, tab) => {
+                if (tab.id === index) {
+                    this.activeIndex = i;
+                    return false;
+                }
+            });
+        }
+        this.setActive();
+    }
+    /**
+     * 在父元素的宽度变化时,需要调用该方法重新调整指示器位置
+     * 在添加或删除选项卡时,需要调用该方法
+     */
+    handleUpdate() {
+        const $oldTabs = this.$tabs; // 旧的 tabs JQ对象
+        const $newTabs = this.$element.children('a'); // 新的 tabs JQ对象
+        const oldTabsElement = $oldTabs.get(); // 旧的 tabs 元素数组
+        const newTabsElement = $newTabs.get(); // 新的 tabs 元素数组
+        if (!$newTabs.length) {
+            this.activeIndex = -1;
+            this.$tabs = $newTabs;
+            this.setIndicatorPosition();
+            return;
+        }
+        // 重新遍历选项卡,找出新增的选项卡
+        $newTabs.each((index, tab) => {
+            // 有新增的选项卡
+            if (oldTabsElement.indexOf(tab) < 0) {
+                this.bindTabEvent(tab);
+                if (this.activeIndex === -1) {
+                    this.activeIndex = 0;
+                }
+                else if (index <= this.activeIndex) {
+                    this.activeIndex++;
+                }
+            }
+        });
+        // 找出被移除的选项卡
+        $oldTabs.each((index, tab) => {
+            // 有被移除的选项卡
+            if (newTabsElement.indexOf(tab) < 0) {
+                if (index < this.activeIndex) {
+                    this.activeIndex--;
+                }
+                else if (index === this.activeIndex) {
+                    this.activeIndex = 0;
+                }
+            }
+        });
+        this.$tabs = $newTabs;
+        this.setActive();
+    }
+}
+mdui.Tab = Tab;
+
+const customAttr$5 = 'mdui-tab';
+$(() => {
+    mdui.mutation(`[${customAttr$5}]`, function () {
+        new mdui.Tab(this, parseOptions(this, customAttr$5));
+    });
+});
+
+/**
+ * 在桌面设备上默认显示抽屉栏,不显示遮罩层
+ * 在手机和平板设备上默认不显示抽屉栏,始终显示遮罩层,且覆盖导航栏
+ */
+const DEFAULT_OPTIONS$5 = {
+    overlay: false,
+    swipe: false,
+};
+class Drawer {
+    constructor(selector, options = {}) {
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS$5);
+        /**
+         * 当前是否显示着遮罩层
+         */
+        this.overlay = false;
+        this.$element = $(selector).first();
+        extend(this.options, options);
+        this.position = this.$element.hasClass('mdui-drawer-right')
+            ? 'right'
+            : 'left';
+        if (this.$element.hasClass('mdui-drawer-close')) {
+            this.state = 'closed';
+        }
+        else if (this.$element.hasClass('mdui-drawer-open')) {
+            this.state = 'opened';
+        }
+        else if (this.isDesktop()) {
+            this.state = 'opened';
+        }
+        else {
+            this.state = 'closed';
+        }
+        // 浏览器窗口大小调整时
+        $window.on('resize', $.throttle(() => {
+            if (this.isDesktop()) {
+                // 由手机平板切换到桌面时
+                // 如果显示着遮罩,则隐藏遮罩
+                if (this.overlay && !this.options.overlay) {
+                    $.hideOverlay();
+                    this.overlay = false;
+                    $.unlockScreen();
+                }
+                // 没有强制关闭,则状态为打开状态
+                if (!this.$element.hasClass('mdui-drawer-close')) {
+                    this.state = 'opened';
+                }
+            }
+            else if (!this.overlay && this.state === 'opened') {
+                // 由桌面切换到手机平板时。如果抽屉栏是打开着的且没有遮罩层,则关闭抽屉栏
+                if (this.$element.hasClass('mdui-drawer-open')) {
+                    $.showOverlay();
+                    this.overlay = true;
+                    $.lockScreen();
+                    $('.mdui-overlay').one('click', () => this.close());
+                }
+                else {
+                    this.state = 'closed';
+                }
+            }
+        }, 100));
+        // 绑定关闭按钮事件
+        this.$element.find('[mdui-drawer-close]').each((_, close) => {
+            $(close).on('click', () => this.close());
+        });
+        this.swipeSupport();
+    }
+    /**
+     * 是否是桌面设备
+     */
+    isDesktop() {
+        return $window.width() >= 1024;
+    }
+    /**
+     * 滑动手势支持
+     */
+    swipeSupport() {
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        const that = this;
+        // 抽屉栏滑动手势控制
+        let openNavEventHandler;
+        let touchStartX;
+        let touchStartY;
+        let swipeStartX;
+        let swiping = null;
+        let maybeSwiping = false;
+        const $body = $('body');
+        // 手势触发的范围
+        const swipeAreaWidth = 24;
+        function setPosition(translateX) {
+            const rtlTranslateMultiplier = that.position === 'right' ? -1 : 1;
+            const transformCSS = `translate(${-1 * rtlTranslateMultiplier * translateX}px, 0) !important;`;
+            const transitionCSS = 'initial !important;';
+            that.$element.css('cssText', `transform: ${transformCSS}; transition: ${transitionCSS};`);
+        }
+        function cleanPosition() {
+            that.$element[0].style.transform = '';
+            that.$element[0].style.webkitTransform = '';
+            that.$element[0].style.transition = '';
+            that.$element[0].style.webkitTransition = '';
+        }
+        function getMaxTranslateX() {
+            return that.$element.width() + 10;
+        }
+        function getTranslateX(currentX) {
+            return Math.min(Math.max(swiping === 'closing'
+                ? swipeStartX - currentX
+                : getMaxTranslateX() + swipeStartX - currentX, 0), getMaxTranslateX());
+        }
+        function onBodyTouchEnd(event) {
+            if (swiping) {
+                let touchX = event.changedTouches[0].pageX;
+                if (that.position === 'right') {
+                    touchX = $body.width() - touchX;
+                }
+                const translateRatio = getTranslateX(touchX) / getMaxTranslateX();
+                maybeSwiping = false;
+                const swipingState = swiping;
+                swiping = null;
+                if (swipingState === 'opening') {
+                    if (translateRatio < 0.92) {
+                        cleanPosition();
+                        that.open();
+                    }
+                    else {
+                        cleanPosition();
+                    }
+                }
+                else {
+                    if (translateRatio > 0.08) {
+                        cleanPosition();
+                        that.close();
+                    }
+                    else {
+                        cleanPosition();
+                    }
+                }
+                $.unlockScreen();
+            }
+            else {
+                maybeSwiping = false;
+            }
+            $body.off({
+                // eslint-disable-next-line @typescript-eslint/no-use-before-define
+                touchmove: onBodyTouchMove,
+                touchend: onBodyTouchEnd,
+                // eslint-disable-next-line @typescript-eslint/no-use-before-define
+                touchcancel: onBodyTouchMove,
+            });
+        }
+        function onBodyTouchMove(event) {
+            let touchX = event.touches[0].pageX;
+            if (that.position === 'right') {
+                touchX = $body.width() - touchX;
+            }
+            const touchY = event.touches[0].pageY;
+            if (swiping) {
+                setPosition(getTranslateX(touchX));
+            }
+            else if (maybeSwiping) {
+                const dXAbs = Math.abs(touchX - touchStartX);
+                const dYAbs = Math.abs(touchY - touchStartY);
+                const threshold = 8;
+                if (dXAbs > threshold && dYAbs <= threshold) {
+                    swipeStartX = touchX;
+                    swiping = that.state === 'opened' ? 'closing' : 'opening';
+                    $.lockScreen();
+                    setPosition(getTranslateX(touchX));
+                }
+                else if (dXAbs <= threshold && dYAbs > threshold) {
+                    onBodyTouchEnd();
+                }
+            }
+        }
+        function onBodyTouchStart(event) {
+            touchStartX = event.touches[0].pageX;
+            if (that.position === 'right') {
+                touchStartX = $body.width() - touchStartX;
+            }
+            touchStartY = event.touches[0].pageY;
+            if (that.state !== 'opened') {
+                if (touchStartX > swipeAreaWidth ||
+                    openNavEventHandler !== onBodyTouchStart) {
+                    return;
+                }
+            }
+            maybeSwiping = true;
+            $body.on({
+                touchmove: onBodyTouchMove,
+                touchend: onBodyTouchEnd,
+                touchcancel: onBodyTouchMove,
+            });
+        }
+        function enableSwipeHandling() {
+            if (!openNavEventHandler) {
+                $body.on('touchstart', onBodyTouchStart);
+                openNavEventHandler = onBodyTouchStart;
+            }
+        }
+        if (this.options.swipe) {
+            enableSwipeHandling();
+        }
+    }
+    /**
+     * 触发组件事件
+     * @param name
+     */
+    triggerEvent(name) {
+        componentEvent(name, 'drawer', this.$element, this);
+    }
+    /**
+     * 动画结束回调
+     */
+    transitionEnd() {
+        if (this.$element.hasClass('mdui-drawer-open')) {
+            this.state = 'opened';
+            this.triggerEvent('opened');
+        }
+        else {
+            this.state = 'closed';
+            this.triggerEvent('closed');
+        }
+    }
+    /**
+     * 是否处于打开状态
+     */
+    isOpen() {
+        return this.state === 'opening' || this.state === 'opened';
+    }
+    /**
+     * 打开抽屉栏
+     */
+    open() {
+        if (this.isOpen()) {
+            return;
+        }
+        this.state = 'opening';
+        this.triggerEvent('open');
+        if (!this.options.overlay) {
+            $('body').addClass(`mdui-drawer-body-${this.position}`);
+        }
+        this.$element
+            .removeClass('mdui-drawer-close')
+            .addClass('mdui-drawer-open')
+            .transitionEnd(() => this.transitionEnd());
+        if (!this.isDesktop() || this.options.overlay) {
+            this.overlay = true;
+            $.showOverlay().one('click', () => this.close());
+            $.lockScreen();
+        }
+    }
+    /**
+     * 关闭抽屉栏
+     */
+    close() {
+        if (!this.isOpen()) {
+            return;
+        }
+        this.state = 'closing';
+        this.triggerEvent('close');
+        if (!this.options.overlay) {
+            $('body').removeClass(`mdui-drawer-body-${this.position}`);
+        }
+        this.$element
+            .addClass('mdui-drawer-close')
+            .removeClass('mdui-drawer-open')
+            .transitionEnd(() => this.transitionEnd());
+        if (this.overlay) {
+            $.hideOverlay();
+            this.overlay = false;
+            $.unlockScreen();
+        }
+    }
+    /**
+     * 切换抽屉栏打开/关闭状态
+     */
+    toggle() {
+        this.isOpen() ? this.close() : this.open();
+    }
+    /**
+     * 返回当前抽屉栏的状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+     */
+    getState() {
+        return this.state;
+    }
+}
+mdui.Drawer = Drawer;
+
+const customAttr$6 = 'mdui-drawer';
+$(() => {
+    mdui.mutation(`[${customAttr$6}]`, function () {
+        const $element = $(this);
+        const options = parseOptions(this, customAttr$6);
+        const selector = options.target;
+        // @ts-ignore
+        delete options.target;
+        const $drawer = $(selector).first();
+        const instance = new mdui.Drawer($drawer, options);
+        $element.on('click', () => instance.toggle());
+    });
+});
+
+const container = {};
+function queue(name, func) {
+    if (isUndefined(container[name])) {
+        container[name] = [];
+    }
+    if (isUndefined(func)) {
+        return container[name];
+    }
+    container[name].push(func);
+}
+/**
+ * 从队列中移除第一个函数,并执行该函数
+ * @param name 队列满
+ */
+function dequeue(name) {
+    if (isUndefined(container[name])) {
+        return;
+    }
+    if (!container[name].length) {
+        return;
+    }
+    const func = container[name].shift();
+    func();
+}
+
+const DEFAULT_OPTIONS$6 = {
+    history: true,
+    overlay: true,
+    modal: false,
+    closeOnEsc: true,
+    closeOnCancel: true,
+    closeOnConfirm: true,
+    destroyOnClosed: false,
+};
+/**
+ * 当前显示的对话框实例
+ */
+let currentInst = null;
+/**
+ * 队列名
+ */
+const queueName = '_mdui_dialog';
+/**
+ * 窗口是否已锁定
+ */
+let isLockScreen = false;
+/**
+ * 遮罩层元素
+ */
+let $overlay;
+class Dialog {
+    constructor(selector, options = {}) {
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS$6);
+        /**
+         * 当前 dialog 的状态
+         */
+        this.state = 'closed';
+        /**
+         * dialog 元素是否是动态添加的
+         */
+        this.append = false;
+        this.$element = $(selector).first();
+        // 如果对话框元素没有在当前文档中,则需要添加
+        if (!contains(document.body, this.$element[0])) {
+            this.append = true;
+            $('body').append(this.$element);
+        }
+        extend(this.options, options);
+        // 绑定取消按钮事件
+        this.$element.find('[mdui-dialog-cancel]').each((_, cancel) => {
+            $(cancel).on('click', () => {
+                this.triggerEvent('cancel');
+                if (this.options.closeOnCancel) {
+                    this.close();
+                }
+            });
+        });
+        // 绑定确认按钮事件
+        this.$element.find('[mdui-dialog-confirm]').each((_, confirm) => {
+            $(confirm).on('click', () => {
+                this.triggerEvent('confirm');
+                if (this.options.closeOnConfirm) {
+                    this.close();
+                }
+            });
+        });
+        // 绑定关闭按钮事件
+        this.$element.find('[mdui-dialog-close]').each((_, close) => {
+            $(close).on('click', () => this.close());
+        });
+    }
+    /**
+     * 触发组件事件
+     * @param name
+     */
+    triggerEvent(name) {
+        componentEvent(name, 'dialog', this.$element, this);
+    }
+    /**
+     * 窗口宽度变化,或对话框内容变化时,调整对话框位置和对话框内的滚动条
+     */
+    readjust() {
+        if (!currentInst) {
+            return;
+        }
+        const $element = currentInst.$element;
+        const $title = $element.children('.mdui-dialog-title');
+        const $content = $element.children('.mdui-dialog-content');
+        const $actions = $element.children('.mdui-dialog-actions');
+        // 调整 dialog 的 top 和 height 值
+        $element.height('');
+        $content.height('');
+        const elementHeight = $element.height();
+        $element.css({
+            top: `${($window.height() - elementHeight) / 2}px`,
+            height: `${elementHeight}px`,
+        });
+        // 调整 mdui-dialog-content 的高度
+        $content.innerHeight(elementHeight -
+            ($title.innerHeight() || 0) -
+            ($actions.innerHeight() || 0));
+    }
+    /**
+     * hashchange 事件触发时关闭对话框
+     */
+    hashchangeEvent() {
+        if (window.location.hash.substring(1).indexOf('mdui-dialog') < 0) {
+            currentInst.close(true);
+        }
+    }
+    /**
+     * 点击遮罩层关闭对话框
+     * @param event
+     */
+    overlayClick(event) {
+        if ($(event.target).hasClass('mdui-overlay') &&
+            currentInst) {
+            currentInst.close();
+        }
+    }
+    /**
+     * 动画结束回调
+     */
+    transitionEnd() {
+        if (this.$element.hasClass('mdui-dialog-open')) {
+            this.state = 'opened';
+            this.triggerEvent('opened');
+        }
+        else {
+            this.state = 'closed';
+            this.triggerEvent('closed');
+            this.$element.hide();
+            // 所有对话框都关闭,且当前没有打开的对话框时,解锁屏幕
+            if (!queue(queueName).length && !currentInst && isLockScreen) {
+                $.unlockScreen();
+                isLockScreen = false;
+            }
+            $window.off('resize', $.throttle(this.readjust, 100));
+            if (this.options.destroyOnClosed) {
+                this.destroy();
+            }
+        }
+    }
+    /**
+     * 打开指定对话框
+     */
+    doOpen() {
+        currentInst = this;
+        if (!isLockScreen) {
+            $.lockScreen();
+            isLockScreen = true;
+        }
+        this.$element.show();
+        this.readjust();
+        $window.on('resize', $.throttle(this.readjust, 100));
+        // 打开消息框
+        this.state = 'opening';
+        this.triggerEvent('open');
+        this.$element
+            .addClass('mdui-dialog-open')
+            .transitionEnd(() => this.transitionEnd());
+        // 不存在遮罩层元素时,添加遮罩层
+        if (!$overlay) {
+            $overlay = $.showOverlay(5100);
+        }
+        // 点击遮罩层时是否关闭对话框
+        if (this.options.modal) {
+            $overlay.off('click', this.overlayClick);
+        }
+        else {
+            $overlay.on('click', this.overlayClick);
+        }
+        // 是否显示遮罩层,不显示时,把遮罩层背景透明
+        $overlay.css('opacity', this.options.overlay ? '' : 0);
+        if (this.options.history) {
+            // 如果 hash 中原来就有 mdui-dialog,先删除,避免后退历史纪录后仍然有 mdui-dialog 导致无法关闭
+            // 包括 mdui-dialog 和 &mdui-dialog 和 ?mdui-dialog
+            let hash = window.location.hash.substring(1);
+            if (hash.indexOf('mdui-dialog') > -1) {
+                hash = hash.replace(/[&?]?mdui-dialog/g, '');
+            }
+            // 后退按钮关闭对话框
+            if (hash) {
+                window.location.hash = `${hash}${hash.indexOf('?') > -1 ? '&' : '?'}mdui-dialog`;
+            }
+            else {
+                window.location.hash = 'mdui-dialog';
+            }
+            $window.on('hashchange', this.hashchangeEvent);
+        }
+    }
+    /**
+     * 当前对话框是否为打开状态
+     */
+    isOpen() {
+        return this.state === 'opening' || this.state === 'opened';
+    }
+    /**
+     * 打开对话框
+     */
+    open() {
+        if (this.isOpen()) {
+            return;
+        }
+        // 如果当前有正在打开或已经打开的对话框,或队列不为空,则先加入队列,等旧对话框开始关闭时再打开
+        if ((currentInst &&
+            (currentInst.state === 'opening' || currentInst.state === 'opened')) ||
+            queue(queueName).length) {
+            queue(queueName, () => this.doOpen());
+            return;
+        }
+        this.doOpen();
+    }
+    /**
+     * 关闭对话框
+     */
+    close(historyBack = false) {
+        // historyBack 是否需要后退历史纪录,默认为 `false`。该参数仅内部使用
+        // 为 `false` 时是通过 js 关闭,需要后退一个历史记录
+        // 为 `true` 时是通过后退按钮关闭,不需要后退历史记录
+        // setTimeout 的作用是:
+        // 当同时关闭一个对话框,并打开另一个对话框时,使打开对话框的操作先执行,以使需要打开的对话框先加入队列
+        setTimeout(() => {
+            if (!this.isOpen()) {
+                return;
+            }
+            currentInst = null;
+            this.state = 'closing';
+            this.triggerEvent('close');
+            // 所有对话框都关闭,且当前没有打开的对话框时,隐藏遮罩
+            if (!queue(queueName).length && $overlay) {
+                $.hideOverlay();
+                $overlay = null;
+                // 若仍存在遮罩,恢复遮罩的 z-index
+                $('.mdui-overlay').css('z-index', 2000);
+            }
+            this.$element
+                .removeClass('mdui-dialog-open')
+                .transitionEnd(() => this.transitionEnd());
+            if (this.options.history && !queue(queueName).length) {
+                if (!historyBack) {
+                    window.history.back();
+                }
+                $window.off('hashchange', this.hashchangeEvent);
+            }
+            // 关闭旧对话框,打开新对话框。
+            // 加一点延迟,仅仅为了视觉效果更好。不加延时也不影响功能
+            setTimeout(() => {
+                dequeue(queueName);
+            }, 100);
+        });
+    }
+    /**
+     * 切换对话框打开/关闭状态
+     */
+    toggle() {
+        this.isOpen() ? this.close() : this.open();
+    }
+    /**
+     * 获取对话框状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+     */
+    getState() {
+        return this.state;
+    }
+    /**
+     * 销毁对话框
+     */
+    destroy() {
+        if (this.append) {
+            this.$element.remove();
+        }
+        if (!queue(queueName).length && !currentInst) {
+            if ($overlay) {
+                $.hideOverlay();
+                $overlay = null;
+            }
+            if (isLockScreen) {
+                $.unlockScreen();
+                isLockScreen = false;
+            }
+        }
+    }
+    /**
+     * 对话框内容变化时,需要调用该方法来调整对话框位置和滚动条高度
+     */
+    handleUpdate() {
+        this.readjust();
+    }
+}
+
+// esc 按下时关闭对话框
+$document.on('keydown', (event) => {
+    if (currentInst &&
+        currentInst.options.closeOnEsc &&
+        currentInst.state === 'opened' &&
+        event.keyCode === 27) {
+        currentInst.close();
+    }
+});
+mdui.Dialog = Dialog;
+
+const customAttr$7 = 'mdui-dialog';
+const dataName$1 = '_mdui_dialog';
+$(() => {
+    $document.on('click', `[${customAttr$7}]`, function () {
+        const options = parseOptions(this, customAttr$7);
+        const selector = options.target;
+        // @ts-ignore
+        delete options.target;
+        const $dialog = $(selector).first();
+        let instance = $dialog.data(dataName$1);
+        if (!instance) {
+            instance = new mdui.Dialog($dialog, options);
+            $dialog.data(dataName$1, instance);
+        }
+        instance.open();
+    });
+});
+
+const DEFAULT_BUTTON = {
+    text: '',
+    bold: false,
+    close: true,
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onClick: () => { },
+};
+const DEFAULT_OPTIONS$7 = {
+    title: '',
+    content: '',
+    buttons: [],
+    stackedButtons: false,
+    cssClass: '',
+    history: true,
+    overlay: true,
+    modal: false,
+    closeOnEsc: true,
+    destroyOnClosed: true,
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onOpen: () => { },
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onOpened: () => { },
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onClose: () => { },
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onClosed: () => { },
+};
+mdui.dialog = function (options) {
+    var _a, _b;
+    // 合并配置参数
+    options = extend({}, DEFAULT_OPTIONS$7, options);
+    each(options.buttons, (i, button) => {
+        options.buttons[i] = extend({}, DEFAULT_BUTTON, button);
+    });
+    // 按钮的 HTML
+    let buttonsHTML = '';
+    if ((_a = options.buttons) === null || _a === void 0 ? void 0 : _a.length) {
+        buttonsHTML = `<div class="mdui-dialog-actions${options.stackedButtons ? ' mdui-dialog-actions-stacked' : ''}">`;
+        each(options.buttons, (_, button) => {
+            buttonsHTML +=
+                '<a href="javascript:void(0)" ' +
+                    `class="mdui-btn mdui-ripple mdui-text-color-primary ${button.bold ? 'mdui-btn-bold' : ''}">${button.text}</a>`;
+        });
+        buttonsHTML += '</div>';
+    }
+    // Dialog 的 HTML
+    const HTML = `<div class="mdui-dialog ${options.cssClass}">` +
+        (options.title
+            ? `<div class="mdui-dialog-title">${options.title}</div>`
+            : '') +
+        (options.content
+            ? `<div class="mdui-dialog-content">${options.content}</div>`
+            : '') +
+        buttonsHTML +
+        '</div>';
+    // 实例化 Dialog
+    const instance = new mdui.Dialog(HTML, {
+        history: options.history,
+        overlay: options.overlay,
+        modal: options.modal,
+        closeOnEsc: options.closeOnEsc,
+        destroyOnClosed: options.destroyOnClosed,
+    });
+    // 绑定按钮事件
+    if ((_b = options.buttons) === null || _b === void 0 ? void 0 : _b.length) {
+        instance.$element
+            .find('.mdui-dialog-actions .mdui-btn')
+            .each((index, button) => {
+            $(button).on('click', () => {
+                options.buttons[index].onClick(instance);
+                if (options.buttons[index].close) {
+                    instance.close();
+                }
+            });
+        });
+    }
+    // 绑定打开关闭事件
+    instance.$element
+        .on('open.mdui.dialog', () => {
+        options.onOpen(instance);
+    })
+        .on('opened.mdui.dialog', () => {
+        options.onOpened(instance);
+    })
+        .on('close.mdui.dialog', () => {
+        options.onClose(instance);
+    })
+        .on('closed.mdui.dialog', () => {
+        options.onClosed(instance);
+    });
+    instance.open();
+    return instance;
+};
+
+const DEFAULT_OPTIONS$8 = {
+    confirmText: 'ok',
+    history: true,
+    modal: false,
+    closeOnEsc: true,
+    closeOnConfirm: true,
+};
+mdui.alert = function (text, title, onConfirm, options) {
+    if (isFunction(title)) {
+        options = onConfirm;
+        onConfirm = title;
+        title = '';
+    }
+    if (isUndefined(onConfirm)) {
+        // eslint-disable-next-line @typescript-eslint/no-empty-function
+        onConfirm = () => { };
+    }
+    if (isUndefined(options)) {
+        options = {};
+    }
+    options = extend({}, DEFAULT_OPTIONS$8, options);
+    return mdui.dialog({
+        title: title,
+        content: text,
+        buttons: [
+            {
+                text: options.confirmText,
+                bold: false,
+                close: options.closeOnConfirm,
+                onClick: onConfirm,
+            },
+        ],
+        cssClass: 'mdui-dialog-alert',
+        history: options.history,
+        modal: options.modal,
+        closeOnEsc: options.closeOnEsc,
+    });
+};
+
+const DEFAULT_OPTIONS$9 = {
+    confirmText: 'ok',
+    cancelText: 'cancel',
+    history: true,
+    modal: false,
+    closeOnEsc: true,
+    closeOnCancel: true,
+    closeOnConfirm: true,
+};
+mdui.confirm = function (text, title, onConfirm, onCancel, options) {
+    if (isFunction(title)) {
+        options = onCancel;
+        onCancel = onConfirm;
+        onConfirm = title;
+        title = '';
+    }
+    if (isUndefined(onConfirm)) {
+        // eslint-disable-next-line @typescript-eslint/no-empty-function
+        onConfirm = () => { };
+    }
+    if (isUndefined(onCancel)) {
+        // eslint-disable-next-line @typescript-eslint/no-empty-function
+        onCancel = () => { };
+    }
+    if (isUndefined(options)) {
+        options = {};
+    }
+    options = extend({}, DEFAULT_OPTIONS$9, options);
+    return mdui.dialog({
+        title: title,
+        content: text,
+        buttons: [
+            {
+                text: options.cancelText,
+                bold: false,
+                close: options.closeOnCancel,
+                onClick: onCancel,
+            },
+            {
+                text: options.confirmText,
+                bold: false,
+                close: options.closeOnConfirm,
+                onClick: onConfirm,
+            },
+        ],
+        cssClass: 'mdui-dialog-confirm',
+        history: options.history,
+        modal: options.modal,
+        closeOnEsc: options.closeOnEsc,
+    });
+};
+
+const DEFAULT_OPTIONS$a = {
+    confirmText: 'ok',
+    cancelText: 'cancel',
+    history: true,
+    modal: false,
+    closeOnEsc: true,
+    closeOnCancel: true,
+    closeOnConfirm: true,
+    type: 'text',
+    maxlength: 0,
+    defaultValue: '',
+    confirmOnEnter: false,
+};
+mdui.prompt = function (label, title, onConfirm, onCancel, options) {
+    if (isFunction(title)) {
+        options = onCancel;
+        onCancel = onConfirm;
+        onConfirm = title;
+        title = '';
+    }
+    if (isUndefined(onConfirm)) {
+        // eslint-disable-next-line @typescript-eslint/no-empty-function
+        onConfirm = () => { };
+    }
+    if (isUndefined(onCancel)) {
+        // eslint-disable-next-line @typescript-eslint/no-empty-function
+        onCancel = () => { };
+    }
+    if (isUndefined(options)) {
+        options = {};
+    }
+    options = extend({}, DEFAULT_OPTIONS$a, options);
+    const content = '<div class="mdui-textfield">' +
+        (label ? `<label class="mdui-textfield-label">${label}</label>` : '') +
+        (options.type === 'text'
+            ? `<input class="mdui-textfield-input" type="text" value="${options.defaultValue}" ${options.maxlength ? 'maxlength="' + options.maxlength + '"' : ''}/>`
+            : '') +
+        (options.type === 'textarea'
+            ? `<textarea class="mdui-textfield-input" ${options.maxlength ? 'maxlength="' + options.maxlength + '"' : ''}>${options.defaultValue}</textarea>`
+            : '') +
+        '</div>';
+    const onCancelClick = (dialog) => {
+        const value = dialog.$element.find('.mdui-textfield-input').val();
+        onCancel(value, dialog);
+    };
+    const onConfirmClick = (dialog) => {
+        const value = dialog.$element.find('.mdui-textfield-input').val();
+        onConfirm(value, dialog);
+    };
+    return mdui.dialog({
+        title,
+        content,
+        buttons: [
+            {
+                text: options.cancelText,
+                bold: false,
+                close: options.closeOnCancel,
+                onClick: onCancelClick,
+            },
+            {
+                text: options.confirmText,
+                bold: false,
+                close: options.closeOnConfirm,
+                onClick: onConfirmClick,
+            },
+        ],
+        cssClass: 'mdui-dialog-prompt',
+        history: options.history,
+        modal: options.modal,
+        closeOnEsc: options.closeOnEsc,
+        onOpen: (dialog) => {
+            // 初始化输入框
+            const $input = dialog.$element.find('.mdui-textfield-input');
+            mdui.updateTextFields($input);
+            // 聚焦到输入框
+            $input[0].focus();
+            // 捕捉文本框回车键,在单行文本框的情况下触发回调
+            if (options.type !== 'textarea' && options.confirmOnEnter === true) {
+                $input.on('keydown', (event) => {
+                    if (event.keyCode === 13) {
+                        const value = dialog.$element.find('.mdui-textfield-input').val();
+                        onConfirm(value, dialog);
+                        if (options.closeOnConfirm) {
+                            dialog.close();
+                        }
+                        return false;
+                    }
+                    return;
+                });
+            }
+            // 如果是多行输入框,监听输入框的 input 事件,更新对话框高度
+            if (options.type === 'textarea') {
+                $input.on('input', () => dialog.handleUpdate());
+            }
+            // 有字符数限制时,加载完文本框后 DOM 会变化,需要更新对话框高度
+            if (options.maxlength) {
+                dialog.handleUpdate();
+            }
+        },
+    });
+};
+
+const DEFAULT_OPTIONS$b = {
+    position: 'auto',
+    delay: 0,
+    content: '',
+};
+class Tooltip {
+    constructor(selector, options = {}) {
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS$b);
+        /**
+         * 当前 tooltip 的状态
+         */
+        this.state = 'closed';
+        /**
+         * setTimeout 的返回值
+         */
+        this.timeoutId = null;
+        this.$target = $(selector).first();
+        extend(this.options, options);
+        // 创建 Tooltip HTML
+        this.$element = $(`<div class="mdui-tooltip" id="${$.guid()}">${this.options.content}</div>`).appendTo(document.body);
+        // 绑定事件。元素处于 disabled 状态时无法触发鼠标事件,为了统一,把 touch 事件也禁用
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        const that = this;
+        this.$target
+            .on('touchstart mouseenter', function (event) {
+            if (that.isDisabled(this)) {
+                return;
+            }
+            if (!isAllow(event)) {
+                return;
+            }
+            register(event);
+            that.open();
+        })
+            .on('touchend mouseleave', function (event) {
+            if (that.isDisabled(this)) {
+                return;
+            }
+            if (!isAllow(event)) {
+                return;
+            }
+            that.close();
+        })
+            .on(unlockEvent, function (event) {
+            if (that.isDisabled(this)) {
+                return;
+            }
+            register(event);
+        });
+    }
+    /**
+     * 元素是否已禁用
+     * @param element
+     */
+    isDisabled(element) {
+        return (element.disabled ||
+            $(element).attr('disabled') !== undefined);
+    }
+    /**
+     * 是否是桌面设备
+     */
+    isDesktop() {
+        return $window.width() > 1024;
+    }
+    /**
+     * 设置 Tooltip 的位置
+     */
+    setPosition() {
+        let marginLeft;
+        let marginTop;
+        // 触发的元素
+        const targetProps = this.$target[0].getBoundingClientRect();
+        // 触发的元素和 Tooltip 之间的距离
+        const targetMargin = this.isDesktop() ? 14 : 24;
+        // Tooltip 的宽度和高度
+        const tooltipWidth = this.$element[0].offsetWidth;
+        const tooltipHeight = this.$element[0].offsetHeight;
+        // Tooltip 的方向
+        let position = this.options.position;
+        // 自动判断位置,加 2px,使 Tooltip 距离窗口边框至少有 2px 的间距
+        if (position === 'auto') {
+            if (targetProps.top +
+                targetProps.height +
+                targetMargin +
+                tooltipHeight +
+                2 <
+                $window.height()) {
+                position = 'bottom';
+            }
+            else if (targetMargin + tooltipHeight + 2 < targetProps.top) {
+                position = 'top';
+            }
+            else if (targetMargin + tooltipWidth + 2 < targetProps.left) {
+                position = 'left';
+            }
+            else if (targetProps.width + targetMargin + tooltipWidth + 2 <
+                $window.width() - targetProps.left) {
+                position = 'right';
+            }
+            else {
+                position = 'bottom';
+            }
+        }
+        // 设置位置
+        switch (position) {
+            case 'bottom':
+                marginLeft = -1 * (tooltipWidth / 2);
+                marginTop = targetProps.height / 2 + targetMargin;
+                this.$element.transformOrigin('top center');
+                break;
+            case 'top':
+                marginLeft = -1 * (tooltipWidth / 2);
+                marginTop =
+                    -1 * (tooltipHeight + targetProps.height / 2 + targetMargin);
+                this.$element.transformOrigin('bottom center');
+                break;
+            case 'left':
+                marginLeft = -1 * (tooltipWidth + targetProps.width / 2 + targetMargin);
+                marginTop = -1 * (tooltipHeight / 2);
+                this.$element.transformOrigin('center right');
+                break;
+            case 'right':
+                marginLeft = targetProps.width / 2 + targetMargin;
+                marginTop = -1 * (tooltipHeight / 2);
+                this.$element.transformOrigin('center left');
+                break;
+        }
+        const targetOffset = this.$target.offset();
+        this.$element.css({
+            top: `${targetOffset.top + targetProps.height / 2}px`,
+            left: `${targetOffset.left + targetProps.width / 2}px`,
+            'margin-left': `${marginLeft}px`,
+            'margin-top': `${marginTop}px`,
+        });
+    }
+    /**
+     * 触发组件事件
+     * @param name
+     */
+    triggerEvent(name) {
+        componentEvent(name, 'tooltip', this.$target, this);
+    }
+    /**
+     * 动画结束回调
+     */
+    transitionEnd() {
+        if (this.$element.hasClass('mdui-tooltip-open')) {
+            this.state = 'opened';
+            this.triggerEvent('opened');
+        }
+        else {
+            this.state = 'closed';
+            this.triggerEvent('closed');
+        }
+    }
+    /**
+     * 当前 tooltip 是否为打开状态
+     */
+    isOpen() {
+        return this.state === 'opening' || this.state === 'opened';
+    }
+    /**
+     * 执行打开 tooltip
+     */
+    doOpen() {
+        this.state = 'opening';
+        this.triggerEvent('open');
+        this.$element
+            .addClass('mdui-tooltip-open')
+            .transitionEnd(() => this.transitionEnd());
+    }
+    /**
+     * 打开 Tooltip
+     * @param options 允许每次打开时设置不同的参数
+     */
+    open(options) {
+        if (this.isOpen()) {
+            return;
+        }
+        const oldOptions = extend({}, this.options);
+        if (options) {
+            extend(this.options, options);
+        }
+        // tooltip 的内容有更新
+        if (oldOptions.content !== this.options.content) {
+            this.$element.html(this.options.content);
+        }
+        this.setPosition();
+        if (this.options.delay) {
+            this.timeoutId = setTimeout(() => this.doOpen(), this.options.delay);
+        }
+        else {
+            this.timeoutId = null;
+            this.doOpen();
+        }
+    }
+    /**
+     * 关闭 Tooltip
+     */
+    close() {
+        if (this.timeoutId) {
+            clearTimeout(this.timeoutId);
+            this.timeoutId = null;
+        }
+        if (!this.isOpen()) {
+            return;
+        }
+        this.state = 'closing';
+        this.triggerEvent('close');
+        this.$element
+            .removeClass('mdui-tooltip-open')
+            .transitionEnd(() => this.transitionEnd());
+    }
+    /**
+     * 切换 Tooltip 的打开状态
+     */
+    toggle() {
+        this.isOpen() ? this.close() : this.open();
+    }
+    /**
+     * 获取 Tooltip 状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+     */
+    getState() {
+        return this.state;
+    }
+}
+mdui.Tooltip = Tooltip;
+
+const customAttr$8 = 'mdui-tooltip';
+const dataName$2 = '_mdui_tooltip';
+$(() => {
+    // mouseenter 不能冒泡,所以这里用 mouseover 代替
+    $document.on('touchstart mouseover', `[${customAttr$8}]`, function () {
+        const $target = $(this);
+        let instance = $target.data(dataName$2);
+        if (!instance) {
+            instance = new mdui.Tooltip(this, parseOptions(this, customAttr$8));
+            $target.data(dataName$2, instance);
+        }
+    });
+});
+
+const DEFAULT_OPTIONS$c = {
+    message: '',
+    timeout: 4000,
+    position: 'bottom',
+    buttonText: '',
+    buttonColor: '',
+    closeOnButtonClick: true,
+    closeOnOutsideClick: true,
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onClick: () => { },
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onButtonClick: () => { },
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onOpen: () => { },
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onOpened: () => { },
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onClose: () => { },
+    // eslint-disable-next-line @typescript-eslint/no-empty-function
+    onClosed: () => { },
+};
+/**
+ * 当前打开着的 Snackbar
+ */
+let currentInst$1 = null;
+/**
+ * 队列名
+ */
+const queueName$1 = '_mdui_snackbar';
+class Snackbar {
+    constructor(options) {
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS$c);
+        /**
+         * 当前 Snackbar 的状态
+         */
+        this.state = 'closed';
+        /**
+         * setTimeout 的 ID
+         */
+        this.timeoutId = null;
+        extend(this.options, options);
+        // 按钮颜色
+        let buttonColorStyle = '';
+        let buttonColorClass = '';
+        if (this.options.buttonColor.indexOf('#') === 0 ||
+            this.options.buttonColor.indexOf('rgb') === 0) {
+            buttonColorStyle = `style="color:${this.options.buttonColor}"`;
+        }
+        else if (this.options.buttonColor !== '') {
+            buttonColorClass = `mdui-text-color-${this.options.buttonColor}`;
+        }
+        // 添加 HTML
+        this.$element = $('<div class="mdui-snackbar">' +
+            `<div class="mdui-snackbar-text">${this.options.message}</div>` +
+            (this.options.buttonText
+                ? `<a href="javascript:void(0)" class="mdui-snackbar-action mdui-btn mdui-ripple mdui-ripple-white ${buttonColorClass}" ${buttonColorStyle}>${this.options.buttonText}</a>`
+                : '') +
+            '</div>').appendTo(document.body);
+        // 设置位置
+        this.setPosition('close');
+        this.$element.reflow().addClass(`mdui-snackbar-${this.options.position}`);
+    }
+    /**
+     * 点击 Snackbar 外面的区域关闭
+     * @param event
+     */
+    closeOnOutsideClick(event) {
+        const $target = $(event.target);
+        if (!$target.hasClass('mdui-snackbar') &&
+            !$target.parents('.mdui-snackbar').length) {
+            currentInst$1.close();
+        }
+    }
+    /**
+     * 设置 Snackbar 的位置
+     * @param state
+     */
+    setPosition(state) {
+        const snackbarHeight = this.$element[0].clientHeight;
+        const position = this.options.position;
+        let translateX;
+        let translateY;
+        // translateX
+        if (position === 'bottom' || position === 'top') {
+            translateX = '-50%';
+        }
+        else {
+            translateX = '0';
+        }
+        // translateY
+        if (state === 'open') {
+            translateY = '0';
+        }
+        else {
+            if (position === 'bottom') {
+                translateY = snackbarHeight;
+            }
+            if (position === 'top') {
+                translateY = -snackbarHeight;
+            }
+            if (position === 'left-top' || position === 'right-top') {
+                translateY = -snackbarHeight - 24;
+            }
+            if (position === 'left-bottom' || position === 'right-bottom') {
+                translateY = snackbarHeight + 24;
+            }
+        }
+        this.$element.transform(`translate(${translateX},${translateY}px`);
+    }
+    /**
+     * 打开 Snackbar
+     */
+    open() {
+        if (this.state === 'opening' || this.state === 'opened') {
+            return;
+        }
+        // 如果当前有正在显示的 Snackbar,则先加入队列,等旧 Snackbar 关闭后再打开
+        if (currentInst$1) {
+            queue(queueName$1, () => this.open());
+            return;
+        }
+        currentInst$1 = this;
+        // 开始打开
+        this.state = 'opening';
+        this.options.onOpen(this);
+        this.setPosition('open');
+        this.$element.transitionEnd(() => {
+            if (this.state !== 'opening') {
+                return;
+            }
+            this.state = 'opened';
+            this.options.onOpened(this);
+            // 有按钮时绑定事件
+            if (this.options.buttonText) {
+                this.$element.find('.mdui-snackbar-action').on('click', () => {
+                    this.options.onButtonClick(this);
+                    if (this.options.closeOnButtonClick) {
+                        this.close();
+                    }
+                });
+            }
+            // 点击 snackbar 的事件
+            this.$element.on('click', (event) => {
+                if (!$(event.target).hasClass('mdui-snackbar-action')) {
+                    this.options.onClick(this);
+                }
+            });
+            // 点击 Snackbar 外面的区域关闭
+            if (this.options.closeOnOutsideClick) {
+                $document.on(startEvent, this.closeOnOutsideClick);
+            }
+            // 超时后自动关闭
+            if (this.options.timeout) {
+                this.timeoutId = setTimeout(() => this.close(), this.options.timeout);
+            }
+        });
+    }
+    /**
+     * 关闭 Snackbar
+     */
+    close() {
+        if (this.state === 'closing' || this.state === 'closed') {
+            return;
+        }
+        if (this.timeoutId) {
+            clearTimeout(this.timeoutId);
+        }
+        if (this.options.closeOnOutsideClick) {
+            $document.off(startEvent, this.closeOnOutsideClick);
+        }
+        this.state = 'closing';
+        this.options.onClose(this);
+        this.setPosition('close');
+        this.$element.transitionEnd(() => {
+            if (this.state !== 'closing') {
+                return;
+            }
+            currentInst$1 = null;
+            this.state = 'closed';
+            this.options.onClosed(this);
+            this.$element.remove();
+            dequeue(queueName$1);
+        });
+    }
+}
+mdui.snackbar = function (message, options = {}) {
+    if (isString(message)) {
+        options.message = message;
+    }
+    else {
+        options = message;
+    }
+    const instance = new Snackbar(options);
+    instance.open();
+    return instance;
+};
+
+$(() => {
+    // 切换导航项
+    $document.on('click', '.mdui-bottom-nav>a', function () {
+        const $item = $(this);
+        const $bottomNav = $item.parent();
+        $bottomNav.children('a').each((index, item) => {
+            const isThis = $item.is(item);
+            if (isThis) {
+                componentEvent('change', 'bottomNav', $bottomNav[0], undefined, {
+                    index,
+                });
+            }
+            isThis
+                ? $(item).addClass('mdui-bottom-nav-active')
+                : $(item).removeClass('mdui-bottom-nav-active');
+        });
+    });
+    // 滚动时隐藏 mdui-bottom-nav-scroll-hide
+    mdui.mutation('.mdui-bottom-nav-scroll-hide', function () {
+        new mdui.Headroom(this, {
+            pinnedClass: 'mdui-headroom-pinned-down',
+            unpinnedClass: 'mdui-headroom-unpinned-down',
+        });
+    });
+});
+
+/**
+ * layer 的 HTML 结构
+ * @param index
+ */
+function layerHTML(index = false) {
+    return (`<div class="mdui-spinner-layer ${index ? `mdui-spinner-layer-${index}` : ''}">` +
+        '<div class="mdui-spinner-circle-clipper mdui-spinner-left">' +
+        '<div class="mdui-spinner-circle"></div>' +
+        '</div>' +
+        '<div class="mdui-spinner-gap-patch">' +
+        '<div class="mdui-spinner-circle"></div>' +
+        '</div>' +
+        '<div class="mdui-spinner-circle-clipper mdui-spinner-right">' +
+        '<div class="mdui-spinner-circle"></div>' +
+        '</div>' +
+        '</div>');
+}
+/**
+ * 填充 HTML
+ * @param spinner
+ */
+function fillHTML(spinner) {
+    const $spinner = $(spinner);
+    const layer = $spinner.hasClass('mdui-spinner-colorful')
+        ? layerHTML(1) + layerHTML(2) + layerHTML(3) + layerHTML(4)
+        : layerHTML();
+    $spinner.html(layer);
+}
+$(() => {
+    // 页面加载完后自动填充 HTML 结构
+    mdui.mutation('.mdui-spinner', function () {
+        fillHTML(this);
+    });
+});
+mdui.updateSpinners = function (selector) {
+    const $elements = isUndefined(selector) ? $('.mdui-spinner') : $(selector);
+    $elements.each(function () {
+        fillHTML(this);
+    });
+};
+
+const DEFAULT_OPTIONS$d = {
+    position: 'auto',
+    align: 'auto',
+    gutter: 16,
+    fixed: false,
+    covered: 'auto',
+    subMenuTrigger: 'hover',
+    subMenuDelay: 200,
+};
+class Menu {
+    constructor(anchorSelector, menuSelector, options = {}) {
+        /**
+         * 配置参数
+         */
+        this.options = extend({}, DEFAULT_OPTIONS$d);
+        /**
+         * 当前菜单状态
+         */
+        this.state = 'closed';
+        this.$anchor = $(anchorSelector).first();
+        this.$element = $(menuSelector).first();
+        // 触发菜单的元素 和 菜单必须是同级的元素,否则菜单可能不能定位
+        if (!this.$anchor.parent().is(this.$element.parent())) {
+            throw new Error('anchorSelector and menuSelector must be siblings');
+        }
+        extend(this.options, options);
+        // 是否是级联菜单
+        this.isCascade = this.$element.hasClass('mdui-menu-cascade');
+        // covered 参数处理
+        this.isCovered =
+            this.options.covered === 'auto' ? !this.isCascade : this.options.covered;
+        // 点击触发菜单切换
+        this.$anchor.on('click', () => this.toggle());
+        // 点击菜单外面区域关闭菜单
+        $document.on('click touchstart', (event) => {
+            const $target = $(event.target);
+            if (this.isOpen() &&
+                !$target.is(this.$element) &&
+                !contains(this.$element[0], $target[0]) &&
+                !$target.is(this.$anchor) &&
+                !contains(this.$anchor[0], $target[0])) {
+                this.close();
+            }
+        });
+        // 点击不含子菜单的菜单条目关闭菜单
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        const that = this;
+        $document.on('click', '.mdui-menu-item', function () {
+            const $item = $(this);
+            if (!$item.find('.mdui-menu').length &&
+                $item.attr('disabled') === undefined) {
+                that.close();
+            }
+        });
+        // 绑定点击或鼠标移入含子菜单的条目的事件
+        this.bindSubMenuEvent();
+        // 窗口大小变化时,重新调整菜单位置
+        $window.on('resize', $.throttle(() => this.readjust(), 100));
+    }
+    /**
+     * 是否为打开状态
+     */
+    isOpen() {
+        return this.state === 'opening' || this.state === 'opened';
+    }
+    /**
+     * 触发组件事件
+     * @param name
+     */
+    triggerEvent(name) {
+        componentEvent(name, 'menu', this.$element, this);
+    }
+    /**
+     * 调整主菜单位置
+     */
+    readjust() {
+        let menuLeft;
+        let menuTop;
+        // 菜单位置和方向
+        let position;
+        let align;
+        // window 窗口的宽度和高度
+        const windowHeight = $window.height();
+        const windowWidth = $window.width();
+        // 配置参数
+        const gutter = this.options.gutter;
+        const isCovered = this.isCovered;
+        const isFixed = this.options.fixed;
+        // 动画方向参数
+        let transformOriginX;
+        let transformOriginY;
+        // 菜单的原始宽度和高度
+        const menuWidth = this.$element.width();
+        const menuHeight = this.$element.height();
+        // 触发菜单的元素在窗口中的位置
+        const anchorRect = this.$anchor[0].getBoundingClientRect();
+        const anchorTop = anchorRect.top;
+        const anchorLeft = anchorRect.left;
+        const anchorHeight = anchorRect.height;
+        const anchorWidth = anchorRect.width;
+        const anchorBottom = windowHeight - anchorTop - anchorHeight;
+        const anchorRight = windowWidth - anchorLeft - anchorWidth;
+        // 触发元素相对其拥有定位属性的父元素的位置
+        const anchorOffsetTop = this.$anchor[0].offsetTop;
+        const anchorOffsetLeft = this.$anchor[0].offsetLeft;
+        // 自动判断菜单位置
+        if (this.options.position === 'auto') {
+            if (anchorBottom + (isCovered ? anchorHeight : 0) > menuHeight + gutter) {
+                // 判断下方是否放得下菜单
+                position = 'bottom';
+            }
+            else if (anchorTop + (isCovered ? anchorHeight : 0) >
+                menuHeight + gutter) {
+                // 判断上方是否放得下菜单
+                position = 'top';
+            }
+            else {
+                // 上下都放不下,居中显示
+                position = 'center';
+            }
+        }
+        else {
+            position = this.options.position;
+        }
+        // 自动判断菜单对齐方式
+        if (this.options.align === 'auto') {
+            if (anchorRight + anchorWidth > menuWidth + gutter) {
+                // 判断右侧是否放得下菜单
+                align = 'left';
+            }
+            else if (anchorLeft + anchorWidth > menuWidth + gutter) {
+                // 判断左侧是否放得下菜单
+                align = 'right';
+            }
+            else {
+                // 左右都放不下,居中显示
+                align = 'center';
+            }
+        }
+        else {
+            align = this.options.align;
+        }
+        // 设置菜单位置
+        if (position === 'bottom') {
+            transformOriginY = '0';
+            menuTop =
+                (isCovered ? 0 : anchorHeight) +
+                    (isFixed ? anchorTop : anchorOffsetTop);
+        }
+        else if (position === 'top') {
+            transformOriginY = '100%';
+            menuTop =
+                (isCovered ? anchorHeight : 0) +
+                    (isFixed ? anchorTop - menuHeight : anchorOffsetTop - menuHeight);
+        }
+        else {
+            transformOriginY = '50%';
+            // =====================在窗口中居中
+            // 显示的菜单的高度,简单菜单高度不超过窗口高度,若超过了则在菜单内部显示滚动条
+            // 级联菜单内部不允许出现滚动条
+            let menuHeightTemp = menuHeight;
+            // 简单菜单比窗口高时,限制菜单高度
+            if (!this.isCascade) {
+                if (menuHeight + gutter * 2 > windowHeight) {
+                    menuHeightTemp = windowHeight - gutter * 2;
+                    this.$element.height(menuHeightTemp);
+                }
+            }
+            menuTop =
+                (windowHeight - menuHeightTemp) / 2 +
+                    (isFixed ? 0 : anchorOffsetTop - anchorTop);
+        }
+        this.$element.css('top', `${menuTop}px`);
+        // 设置菜单对齐方式
+        if (align === 'left') {
+            transformOriginX = '0';
+            menuLeft = isFixed ? anchorLeft : anchorOffsetLeft;
+        }
+        else if (align === 'right') {
+            transformOriginX = '100%';
+            menuLeft = isFixed
+                ? anchorLeft + anchorWidth - menuWidth
+                : anchorOffsetLeft + anchorWidth - menuWidth;
+        }
+        else {
+            transformOriginX = '50%';
+            //=======================在窗口中居中
+            // 显示的菜单的宽度,菜单宽度不能超过窗口宽度
+            let menuWidthTemp = menuWidth;
+            // 菜单比窗口宽,限制菜单宽度
+            if (menuWidth + gutter * 2 > windowWidth) {
+                menuWidthTemp = windowWidth - gutter * 2;
+                this.$element.width(menuWidthTemp);
+            }
+            menuLeft =
+                (windowWidth - menuWidthTemp) / 2 +
+                    (isFixed ? 0 : anchorOffsetLeft - anchorLeft);
+        }
+        this.$element.css('left', `${menuLeft}px`);
+        // 设置菜单动画方向
+        this.$element.transformOrigin(`${transformOriginX} ${transformOriginY}`);
+    }
+    /**
+     * 调整子菜单的位置
+     * @param $submenu
+     */
+    readjustSubmenu($submenu) {
+        const $item = $submenu.parent('.mdui-menu-item');
+        let submenuTop;
+        let submenuLeft;
+        // 子菜单位置和方向
+        let position;
+        let align;
+        // window 窗口的宽度和高度
+        const windowHeight = $window.height();
+        const windowWidth = $window.width();
+        // 动画方向参数
+        let transformOriginX;
+        let transformOriginY;
+        // 子菜单的原始宽度和高度
+        const submenuWidth = $submenu.width();
+        const submenuHeight = $submenu.height();
+        // 触发子菜单的菜单项的宽度高度
+        const itemRect = $item[0].getBoundingClientRect();
+        const itemWidth = itemRect.width;
+        const itemHeight = itemRect.height;
+        const itemLeft = itemRect.left;
+        const itemTop = itemRect.top;
+        // 判断菜单上下位置
+        if (windowHeight - itemTop > submenuHeight) {
+            // 判断下方是否放得下菜单
+            position = 'bottom';
+        }
+        else if (itemTop + itemHeight > submenuHeight) {
+            // 判断上方是否放得下菜单
+            position = 'top';
+        }
+        else {
+            // 默认放在下方
+            position = 'bottom';
+        }
+        // 判断菜单左右位置
+        if (windowWidth - itemLeft - itemWidth > submenuWidth) {
+            // 判断右侧是否放得下菜单
+            align = 'left';
+        }
+        else if (itemLeft > submenuWidth) {
+            // 判断左侧是否放得下菜单
+            align = 'right';
+        }
+        else {
+            // 默认放在右侧
+            align = 'left';
+        }
+        // 设置菜单位置
+        if (position === 'bottom') {
+            transformOriginY = '0';
+            submenuTop = '0';
+        }
+        else if (position === 'top') {
+            transformOriginY = '100%';
+            submenuTop = -submenuHeight + itemHeight;
+        }
+        $submenu.css('top', `${submenuTop}px`);
+        // 设置菜单对齐方式
+        if (align === 'left') {
+            transformOriginX = '0';
+            submenuLeft = itemWidth;
+        }
+        else if (align === 'right') {
+            transformOriginX = '100%';
+            submenuLeft = -submenuWidth;
+        }
+        $submenu.css('left', `${submenuLeft}px`);
+        // 设置菜单动画方向
+        $submenu.transformOrigin(`${transformOriginX} ${transformOriginY}`);
+    }
+    /**
+     * 打开子菜单
+     * @param $submenu
+     */
+    openSubMenu($submenu) {
+        this.readjustSubmenu($submenu);
+        $submenu
+            .addClass('mdui-menu-open')
+            .parent('.mdui-menu-item')
+            .addClass('mdui-menu-item-active');
+    }
+    /**
+     * 关闭子菜单,及其嵌套的子菜单
+     * @param $submenu
+     */
+    closeSubMenu($submenu) {
+        // 关闭子菜单
+        $submenu
+            .removeClass('mdui-menu-open')
+            .addClass('mdui-menu-closing')
+            .transitionEnd(() => $submenu.removeClass('mdui-menu-closing'))
+            // 移除激活状态的样式
+            .parent('.mdui-menu-item')
+            .removeClass('mdui-menu-item-active');
+        // 循环关闭嵌套的子菜单
+        $submenu.find('.mdui-menu').each((_, menu) => {
+            const $subSubmenu = $(menu);
+            $subSubmenu
+                .removeClass('mdui-menu-open')
+                .addClass('mdui-menu-closing')
+                .transitionEnd(() => $subSubmenu.removeClass('mdui-menu-closing'))
+                .parent('.mdui-menu-item')
+                .removeClass('mdui-menu-item-active');
+        });
+    }
+    /**
+     * 切换子菜单状态
+     * @param $submenu
+     */
+    toggleSubMenu($submenu) {
+        $submenu.hasClass('mdui-menu-open')
+            ? this.closeSubMenu($submenu)
+            : this.openSubMenu($submenu);
+    }
+    /**
+     * 绑定子菜单事件
+     */
+    bindSubMenuEvent() {
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        const that = this;
+        // 点击打开子菜单
+        this.$element.on('click', '.mdui-menu-item', function (event) {
+            const $item = $(this);
+            const $target = $(event.target);
+            // 禁用状态菜单不操作
+            if ($item.attr('disabled') !== undefined) {
+                return;
+            }
+            // 没有点击在子菜单的菜单项上时,不操作(点在了子菜单的空白区域、或分隔线上)
+            if ($target.is('.mdui-menu') || $target.is('.mdui-divider')) {
+                return;
+            }
+            // 阻止冒泡,点击菜单项时只在最后一级的 mdui-menu-item 上生效,不向上冒泡
+            if (!$target.parents('.mdui-menu-item').first().is($item)) {
+                return;
+            }
+            // 当前菜单的子菜单
+            const $submenu = $item.children('.mdui-menu');
+            // 先关闭除当前子菜单外的所有同级子菜单
+            $item
+                .parent('.mdui-menu')
+                .children('.mdui-menu-item')
+                .each((_, item) => {
+                const $tmpSubmenu = $(item).children('.mdui-menu');
+                if ($tmpSubmenu.length &&
+                    (!$submenu.length || !$tmpSubmenu.is($submenu))) {
+                    that.closeSubMenu($tmpSubmenu);
+                }
+            });
+            // 切换当前子菜单
+            if ($submenu.length) {
+                that.toggleSubMenu($submenu);
+            }
+        });
+        if (this.options.subMenuTrigger === 'hover') {
+            // 临时存储 setTimeout 对象
+            let timeout = null;
+            let timeoutOpen = null;
+            this.$element.on('mouseover mouseout', '.mdui-menu-item', function (event) {
+                const $item = $(this);
+                const eventType = event.type;
+                const $relatedTarget = $(event.relatedTarget);
+                // 禁用状态的菜单不操作
+                if ($item.attr('disabled') !== undefined) {
+                    return;
+                }
+                // 用 mouseover 模拟 mouseenter
+                if (eventType === 'mouseover') {
+                    if (!$item.is($relatedTarget) &&
+                        contains($item[0], $relatedTarget[0])) {
+                        return;
+                    }
+                }
+                // 用 mouseout 模拟 mouseleave
+                else if (eventType === 'mouseout') {
+                    if ($item.is($relatedTarget) ||
+                        contains($item[0], $relatedTarget[0])) {
+                        return;
+                    }
+                }
+                // 当前菜单项下的子菜单,未必存在
+                const $submenu = $item.children('.mdui-menu');
+                // 鼠标移入菜单项时,显示菜单项下的子菜单
+                if (eventType === 'mouseover') {
+                    if ($submenu.length) {
+                        // 当前子菜单准备打开时,如果当前子菜单正准备着关闭,不用再关闭了
+                        const tmpClose = $submenu.data('timeoutClose.mdui.menu');
+                        if (tmpClose) {
+                            clearTimeout(tmpClose);
+                        }
+                        // 如果当前子菜单已经打开,不操作
+                        if ($submenu.hasClass('mdui-menu-open')) {
+                            return;
+                        }
+                        // 当前子菜单准备打开时,其他准备打开的子菜单不用再打开了
+                        clearTimeout(timeoutOpen);
+                        // 准备打开当前子菜单
+                        timeout = timeoutOpen = setTimeout(() => that.openSubMenu($submenu), that.options.subMenuDelay);
+                        $submenu.data('timeoutOpen.mdui.menu', timeout);
+                    }
+                }
+                // 鼠标移出菜单项时,关闭菜单项下的子菜单
+                else if (eventType === 'mouseout') {
+                    if ($submenu.length) {
+                        // 鼠标移出菜单项时,如果当前菜单项下的子菜单正准备打开,不用再打开了
+                        const tmpOpen = $submenu.data('timeoutOpen.mdui.menu');
+                        if (tmpOpen) {
+                            clearTimeout(tmpOpen);
+                        }
+                        // 准备关闭当前子菜单
+                        timeout = setTimeout(() => that.closeSubMenu($submenu), that.options.subMenuDelay);
+                        $submenu.data('timeoutClose.mdui.menu', timeout);
+                    }
+                }
+            });
+        }
+    }
+    /**
+     * 动画结束回调
+     */
+    transitionEnd() {
+        this.$element.removeClass('mdui-menu-closing');
+        if (this.state === 'opening') {
+            this.state = 'opened';
+            this.triggerEvent('opened');
+        }
+        if (this.state === 'closing') {
+            this.state = 'closed';
+            this.triggerEvent('closed');
+            // 关闭后,恢复菜单样式到默认状态,并恢复 fixed 定位
+            this.$element.css({
+                top: '',
+                left: '',
+                width: '',
+                position: 'fixed',
+            });
+        }
+    }
+    /**
+     * 切换菜单状态
+     */
+    toggle() {
+        this.isOpen() ? this.close() : this.open();
+    }
+    /**
+     * 打开菜单
+     */
+    open() {
+        if (this.isOpen()) {
+            return;
+        }
+        this.state = 'opening';
+        this.triggerEvent('open');
+        this.readjust();
+        this.$element
+            // 菜单隐藏状态使用使用 fixed 定位。
+            .css('position', this.options.fixed ? 'fixed' : 'absolute')
+            .addClass('mdui-menu-open')
+            .transitionEnd(() => this.transitionEnd());
+    }
+    /**
+     * 关闭菜单
+     */
+    close() {
+        if (!this.isOpen()) {
+            return;
+        }
+        this.state = 'closing';
+        this.triggerEvent('close');
+        // 菜单开始关闭时,关闭所有子菜单
+        this.$element.find('.mdui-menu').each((_, submenu) => {
+            this.closeSubMenu($(submenu));
+        });
+        this.$element
+            .removeClass('mdui-menu-open')
+            .addClass('mdui-menu-closing')
+            .transitionEnd(() => this.transitionEnd());
+    }
+}
+mdui.Menu = Menu;
+
+const customAttr$9 = 'mdui-menu';
+const dataName$3 = '_mdui_menu';
+$(() => {
+    $document.on('click', `[${customAttr$9}]`, function () {
+        const $this = $(this);
+        let instance = $this.data(dataName$3);
+        if (!instance) {
+            const options = parseOptions(this, customAttr$9);
+            const menuSelector = options.target;
+            // @ts-ignore
+            delete options.target;
+            instance = new mdui.Menu($this, menuSelector, options);
+            $this.data(dataName$3, instance);
+            instance.toggle();
+        }
+    });
+});
+
+export default mdui;
+//# sourceMappingURL=mdui.esm.js.map

File diff suppressed because it is too large
+ 0 - 0
koyeb/web/js/mdui.esm.js.map


+ 6474 - 0
koyeb/web/js/mdui.js

@@ -0,0 +1,6474 @@
+/*!
+ * mdui 1.0.2 (https://mdui.org)
+ * Copyright 2016-2021 zdhxiong
+ * Licensed under MIT
+ */
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+  typeof define === 'function' && define.amd ? define(factory) :
+  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.mdui = factory());
+}(this, (function () { 'use strict';
+
+  !function(){try{return new MouseEvent("test")}catch(e$1){}var e=function(e,t){t=t||{bubbles:!1,cancelable:!1};var n=document.createEvent("MouseEvent");return n.initMouseEvent(e,t.bubbles,t.cancelable,window,0,t.screenX||0,t.screenY||0,t.clientX||0,t.clientY||0,t.ctrlKey||!1,t.altKey||!1,t.shiftKey||!1,t.metaKey||!1,t.button||0,t.relatedTarget||null),n};e.prototype=Event.prototype,window.MouseEvent=e;}();
+
+  !function(){function t(t,e){e=e||{bubbles:!1,cancelable:!1,detail:void 0};var n=document.createEvent("CustomEvent");return n.initCustomEvent(t,e.bubbles,e.cancelable,e.detail),n}"function"!=typeof window.CustomEvent&&(t.prototype=window.Event.prototype,window.CustomEvent=t);}();
+
+  /**
+   * @this {Promise}
+   */
+  function finallyConstructor(callback) {
+    var constructor = this.constructor;
+    return this.then(
+      function(value) {
+        // @ts-ignore
+        return constructor.resolve(callback()).then(function() {
+          return value;
+        });
+      },
+      function(reason) {
+        // @ts-ignore
+        return constructor.resolve(callback()).then(function() {
+          // @ts-ignore
+          return constructor.reject(reason);
+        });
+      }
+    );
+  }
+
+  function allSettled(arr) {
+    var P = this;
+    return new P(function(resolve, reject) {
+      if (!(arr && typeof arr.length !== 'undefined')) {
+        return reject(
+          new TypeError(
+            typeof arr +
+              ' ' +
+              arr +
+              ' is not iterable(cannot read property Symbol(Symbol.iterator))'
+          )
+        );
+      }
+      var args = Array.prototype.slice.call(arr);
+      if (args.length === 0) { return resolve([]); }
+      var remaining = args.length;
+
+      function res(i, val) {
+        if (val && (typeof val === 'object' || typeof val === 'function')) {
+          var then = val.then;
+          if (typeof then === 'function') {
+            then.call(
+              val,
+              function(val) {
+                res(i, val);
+              },
+              function(e) {
+                args[i] = { status: 'rejected', reason: e };
+                if (--remaining === 0) {
+                  resolve(args);
+                }
+              }
+            );
+            return;
+          }
+        }
+        args[i] = { status: 'fulfilled', value: val };
+        if (--remaining === 0) {
+          resolve(args);
+        }
+      }
+
+      for (var i = 0; i < args.length; i++) {
+        res(i, args[i]);
+      }
+    });
+  }
+
+  // Store setTimeout reference so promise-polyfill will be unaffected by
+  // other code modifying setTimeout (like sinon.useFakeTimers())
+  var setTimeoutFunc = setTimeout;
+
+  function isArray(x) {
+    return Boolean(x && typeof x.length !== 'undefined');
+  }
+
+  function noop() {}
+
+  // Polyfill for Function.prototype.bind
+  function bind(fn, thisArg) {
+    return function() {
+      fn.apply(thisArg, arguments);
+    };
+  }
+
+  /**
+   * @constructor
+   * @param {Function} fn
+   */
+  function Promise$1(fn) {
+    if (!(this instanceof Promise$1))
+      { throw new TypeError('Promises must be constructed via new'); }
+    if (typeof fn !== 'function') { throw new TypeError('not a function'); }
+    /** @type {!number} */
+    this._state = 0;
+    /** @type {!boolean} */
+    this._handled = false;
+    /** @type {Promise|undefined} */
+    this._value = undefined;
+    /** @type {!Array<!Function>} */
+    this._deferreds = [];
+
+    doResolve(fn, this);
+  }
+
+  function handle(self, deferred) {
+    while (self._state === 3) {
+      self = self._value;
+    }
+    if (self._state === 0) {
+      self._deferreds.push(deferred);
+      return;
+    }
+    self._handled = true;
+    Promise$1._immediateFn(function() {
+      var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
+      if (cb === null) {
+        (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
+        return;
+      }
+      var ret;
+      try {
+        ret = cb(self._value);
+      } catch (e) {
+        reject(deferred.promise, e);
+        return;
+      }
+      resolve(deferred.promise, ret);
+    });
+  }
+
+  function resolve(self, newValue) {
+    try {
+      // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
+      if (newValue === self)
+        { throw new TypeError('A promise cannot be resolved with itself.'); }
+      if (
+        newValue &&
+        (typeof newValue === 'object' || typeof newValue === 'function')
+      ) {
+        var then = newValue.then;
+        if (newValue instanceof Promise$1) {
+          self._state = 3;
+          self._value = newValue;
+          finale(self);
+          return;
+        } else if (typeof then === 'function') {
+          doResolve(bind(then, newValue), self);
+          return;
+        }
+      }
+      self._state = 1;
+      self._value = newValue;
+      finale(self);
+    } catch (e) {
+      reject(self, e);
+    }
+  }
+
+  function reject(self, newValue) {
+    self._state = 2;
+    self._value = newValue;
+    finale(self);
+  }
+
+  function finale(self) {
+    if (self._state === 2 && self._deferreds.length === 0) {
+      Promise$1._immediateFn(function() {
+        if (!self._handled) {
+          Promise$1._unhandledRejectionFn(self._value);
+        }
+      });
+    }
+
+    for (var i = 0, len = self._deferreds.length; i < len; i++) {
+      handle(self, self._deferreds[i]);
+    }
+    self._deferreds = null;
+  }
+
+  /**
+   * @constructor
+   */
+  function Handler(onFulfilled, onRejected, promise) {
+    this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
+    this.onRejected = typeof onRejected === 'function' ? onRejected : null;
+    this.promise = promise;
+  }
+
+  /**
+   * Take a potentially misbehaving resolver function and make sure
+   * onFulfilled and onRejected are only called once.
+   *
+   * Makes no guarantees about asynchrony.
+   */
+  function doResolve(fn, self) {
+    var done = false;
+    try {
+      fn(
+        function(value) {
+          if (done) { return; }
+          done = true;
+          resolve(self, value);
+        },
+        function(reason) {
+          if (done) { return; }
+          done = true;
+          reject(self, reason);
+        }
+      );
+    } catch (ex) {
+      if (done) { return; }
+      done = true;
+      reject(self, ex);
+    }
+  }
+
+  Promise$1.prototype['catch'] = function(onRejected) {
+    return this.then(null, onRejected);
+  };
+
+  Promise$1.prototype.then = function(onFulfilled, onRejected) {
+    // @ts-ignore
+    var prom = new this.constructor(noop);
+
+    handle(this, new Handler(onFulfilled, onRejected, prom));
+    return prom;
+  };
+
+  Promise$1.prototype['finally'] = finallyConstructor;
+
+  Promise$1.all = function(arr) {
+    return new Promise$1(function(resolve, reject) {
+      if (!isArray(arr)) {
+        return reject(new TypeError('Promise.all accepts an array'));
+      }
+
+      var args = Array.prototype.slice.call(arr);
+      if (args.length === 0) { return resolve([]); }
+      var remaining = args.length;
+
+      function res(i, val) {
+        try {
+          if (val && (typeof val === 'object' || typeof val === 'function')) {
+            var then = val.then;
+            if (typeof then === 'function') {
+              then.call(
+                val,
+                function(val) {
+                  res(i, val);
+                },
+                reject
+              );
+              return;
+            }
+          }
+          args[i] = val;
+          if (--remaining === 0) {
+            resolve(args);
+          }
+        } catch (ex) {
+          reject(ex);
+        }
+      }
+
+      for (var i = 0; i < args.length; i++) {
+        res(i, args[i]);
+      }
+    });
+  };
+
+  Promise$1.allSettled = allSettled;
+
+  Promise$1.resolve = function(value) {
+    if (value && typeof value === 'object' && value.constructor === Promise$1) {
+      return value;
+    }
+
+    return new Promise$1(function(resolve) {
+      resolve(value);
+    });
+  };
+
+  Promise$1.reject = function(value) {
+    return new Promise$1(function(resolve, reject) {
+      reject(value);
+    });
+  };
+
+  Promise$1.race = function(arr) {
+    return new Promise$1(function(resolve, reject) {
+      if (!isArray(arr)) {
+        return reject(new TypeError('Promise.race accepts an array'));
+      }
+
+      for (var i = 0, len = arr.length; i < len; i++) {
+        Promise$1.resolve(arr[i]).then(resolve, reject);
+      }
+    });
+  };
+
+  // Use polyfill for setImmediate for performance gains
+  Promise$1._immediateFn =
+    // @ts-ignore
+    (typeof setImmediate === 'function' &&
+      function(fn) {
+        // @ts-ignore
+        setImmediate(fn);
+      }) ||
+    function(fn) {
+      setTimeoutFunc(fn, 0);
+    };
+
+  Promise$1._unhandledRejectionFn = function _unhandledRejectionFn(err) {
+    if (typeof console !== 'undefined' && console) {
+      console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
+    }
+  };
+
+  /** @suppress {undefinedVars} */
+  var globalNS = (function() {
+    // the only reliable means to get the global object is
+    // `Function('return this')()`
+    // However, this causes CSP violations in Chrome apps.
+    if (typeof self !== 'undefined') {
+      return self;
+    }
+    if (typeof window !== 'undefined') {
+      return window;
+    }
+    if (typeof global !== 'undefined') {
+      return global;
+    }
+    throw new Error('unable to locate global object');
+  })();
+
+  // Expose the polyfill if Promise is undefined or set to a
+  // non-function value. The latter can be due to a named HTMLElement
+  // being exposed by browsers for legacy reasons.
+  // https://github.com/taylorhakes/promise-polyfill/issues/114
+  if (typeof globalNS['Promise'] !== 'function') {
+    globalNS['Promise'] = Promise$1;
+  } else if (!globalNS.Promise.prototype['finally']) {
+    globalNS.Promise.prototype['finally'] = finallyConstructor;
+  } else if (!globalNS.Promise.allSettled) {
+    globalNS.Promise.allSettled = allSettled;
+  }
+
+  function isFunction(target) {
+      return typeof target === 'function';
+  }
+  function isString(target) {
+      return typeof target === 'string';
+  }
+  function isNumber(target) {
+      return typeof target === 'number';
+  }
+  function isBoolean(target) {
+      return typeof target === 'boolean';
+  }
+  function isUndefined(target) {
+      return typeof target === 'undefined';
+  }
+  function isNull(target) {
+      return target === null;
+  }
+  function isWindow(target) {
+      return target instanceof Window;
+  }
+  function isDocument(target) {
+      return target instanceof Document;
+  }
+  function isElement(target) {
+      return target instanceof Element;
+  }
+  function isNode(target) {
+      return target instanceof Node;
+  }
+  /**
+   * 是否是 IE 浏览器
+   */
+  function isIE() {
+      // @ts-ignore
+      return !!window.document.documentMode;
+  }
+  function isArrayLike(target) {
+      if (isFunction(target) || isWindow(target)) {
+          return false;
+      }
+      return isNumber(target.length);
+  }
+  function isObjectLike(target) {
+      return typeof target === 'object' && target !== null;
+  }
+  function toElement(target) {
+      return isDocument(target) ? target.documentElement : target;
+  }
+  /**
+   * 把用 - 分隔的字符串转为驼峰(如 box-sizing 转换为 boxSizing)
+   * @param string
+   */
+  function toCamelCase(string) {
+      return string
+          .replace(/^-ms-/, 'ms-')
+          .replace(/-([a-z])/g, function (_, letter) { return letter.toUpperCase(); });
+  }
+  /**
+   * 把驼峰法转为用 - 分隔的字符串(如 boxSizing 转换为 box-sizing)
+   * @param string
+   */
+  function toKebabCase(string) {
+      return string.replace(/[A-Z]/g, function (replacer) { return '-' + replacer.toLowerCase(); });
+  }
+  /**
+   * 获取元素的样式值
+   * @param element
+   * @param name
+   */
+  function getComputedStyleValue(element, name) {
+      return window.getComputedStyle(element).getPropertyValue(toKebabCase(name));
+  }
+  /**
+   * 检查元素的 box-sizing 是否是 border-box
+   * @param element
+   */
+  function isBorderBox(element) {
+      return getComputedStyleValue(element, 'box-sizing') === 'border-box';
+  }
+  /**
+   * 获取元素的 padding, border, margin 宽度(两侧宽度的和,单位为px)
+   * @param element
+   * @param direction
+   * @param extra
+   */
+  function getExtraWidth(element, direction, extra) {
+      var position = direction === 'width' ? ['Left', 'Right'] : ['Top', 'Bottom'];
+      return [0, 1].reduce(function (prev, _, index) {
+          var prop = extra + position[index];
+          if (extra === 'border') {
+              prop += 'Width';
+          }
+          return prev + parseFloat(getComputedStyleValue(element, prop) || '0');
+      }, 0);
+  }
+  /**
+   * 获取元素的样式值,对 width 和 height 进行过处理
+   * @param element
+   * @param name
+   */
+  function getStyle(element, name) {
+      // width、height 属性使用 getComputedStyle 得到的值不准确,需要使用 getBoundingClientRect 获取
+      if (name === 'width' || name === 'height') {
+          var valueNumber = element.getBoundingClientRect()[name];
+          if (isBorderBox(element)) {
+              return (valueNumber + "px");
+          }
+          return ((valueNumber -
+              getExtraWidth(element, name, 'border') -
+              getExtraWidth(element, name, 'padding')) + "px");
+      }
+      return getComputedStyleValue(element, name);
+  }
+  /**
+   * 获取子节点组成的数组
+   * @param target
+   * @param parent
+   */
+  function getChildNodesArray(target, parent) {
+      var tempParent = document.createElement(parent);
+      tempParent.innerHTML = target;
+      return [].slice.call(tempParent.childNodes);
+  }
+  /**
+   * 始终返回 false 的函数
+   */
+  function returnFalse() {
+      return false;
+  }
+  /**
+   * 数值单位的 CSS 属性
+   */
+  var cssNumber = [
+      'animationIterationCount',
+      'columnCount',
+      'fillOpacity',
+      'flexGrow',
+      'flexShrink',
+      'fontWeight',
+      'gridArea',
+      'gridColumn',
+      'gridColumnEnd',
+      'gridColumnStart',
+      'gridRow',
+      'gridRowEnd',
+      'gridRowStart',
+      'lineHeight',
+      'opacity',
+      'order',
+      'orphans',
+      'widows',
+      'zIndex',
+      'zoom' ];
+
+  function each(target, callback) {
+      if (isArrayLike(target)) {
+          for (var i = 0; i < target.length; i += 1) {
+              if (callback.call(target[i], i, target[i]) === false) {
+                  return target;
+              }
+          }
+      }
+      else {
+          var keys = Object.keys(target);
+          for (var i$1 = 0; i$1 < keys.length; i$1 += 1) {
+              if (callback.call(target[keys[i$1]], keys[i$1], target[keys[i$1]]) === false) {
+                  return target;
+              }
+          }
+      }
+      return target;
+  }
+
+  /**
+   * 为了使用模块扩充,这里不能使用默认导出
+   */
+  var JQ = function JQ(arr) {
+      var this$1 = this;
+
+      this.length = 0;
+      if (!arr) {
+          return this;
+      }
+      each(arr, function (i, item) {
+          // @ts-ignore
+          this$1[i] = item;
+      });
+      this.length = arr.length;
+      return this;
+  };
+
+  function get$() {
+      var $ = function (selector) {
+          if (!selector) {
+              return new JQ();
+          }
+          // JQ
+          if (selector instanceof JQ) {
+              return selector;
+          }
+          // function
+          if (isFunction(selector)) {
+              if (/complete|loaded|interactive/.test(document.readyState) &&
+                  document.body) {
+                  selector.call(document, $);
+              }
+              else {
+                  document.addEventListener('DOMContentLoaded', function () { return selector.call(document, $); }, false);
+              }
+              return new JQ([document]);
+          }
+          // String
+          if (isString(selector)) {
+              var html = selector.trim();
+              // 根据 HTML 字符串创建 JQ 对象
+              if (html[0] === '<' && html[html.length - 1] === '>') {
+                  var toCreate = 'div';
+                  var tags = {
+                      li: 'ul',
+                      tr: 'tbody',
+                      td: 'tr',
+                      th: 'tr',
+                      tbody: 'table',
+                      option: 'select',
+                  };
+                  each(tags, function (childTag, parentTag) {
+                      if (html.indexOf(("<" + childTag)) === 0) {
+                          toCreate = parentTag;
+                          return false;
+                      }
+                      return;
+                  });
+                  return new JQ(getChildNodesArray(html, toCreate));
+              }
+              // 根据 CSS 选择器创建 JQ 对象
+              var isIdSelector = selector[0] === '#' && !selector.match(/[ .<>:~]/);
+              if (!isIdSelector) {
+                  return new JQ(document.querySelectorAll(selector));
+              }
+              var element = document.getElementById(selector.slice(1));
+              if (element) {
+                  return new JQ([element]);
+              }
+              return new JQ();
+          }
+          if (isArrayLike(selector) && !isNode(selector)) {
+              return new JQ(selector);
+          }
+          return new JQ([selector]);
+      };
+      $.fn = JQ.prototype;
+      return $;
+  }
+  var $ = get$();
+
+  // 避免页面加载完后直接执行css动画
+  // https://css-tricks.com/transitions-only-after-page-load/
+  setTimeout(function () { return $('body').addClass('mdui-loaded'); });
+  var mdui = {
+      $: $,
+  };
+
+  $.fn.each = function (callback) {
+      return each(this, callback);
+  };
+
+  /**
+   * 检查 container 元素内是否包含 contains 元素
+   * @param container 父元素
+   * @param contains 子元素
+   * @example
+  ```js
+  contains( document, document.body ); // true
+  contains( document.getElementById('test'), document ); // false
+  contains( $('.container').get(0), $('.contains').get(0) ); // false
+  ```
+   */
+  function contains(container, contains) {
+      return container !== contains && toElement(container).contains(contains);
+  }
+
+  /**
+   * 把第二个数组的元素追加到第一个数组中,并返回合并后的数组
+   * @param first 第一个数组
+   * @param second 该数组的元素将被追加到第一个数组中
+   * @example
+  ```js
+  merge( [ 0, 1, 2 ], [ 2, 3, 4 ] )
+  // [ 0, 1, 2, 2, 3, 4 ]
+  ```
+   */
+  function merge(first, second) {
+      each(second, function (_, value) {
+          first.push(value);
+      });
+      return first;
+  }
+
+  $.fn.get = function (index) {
+      return index === undefined
+          ? [].slice.call(this)
+          : this[index >= 0 ? index : index + this.length];
+  };
+
+  $.fn.find = function (selector) {
+      var foundElements = [];
+      this.each(function (_, element) {
+          merge(foundElements, $(element.querySelectorAll(selector)).get());
+      });
+      return new JQ(foundElements);
+  };
+
+  // 存储事件
+  var handlers = {};
+  // 元素ID
+  var mduiElementId = 1;
+  /**
+   * 为元素赋予一个唯一的ID
+   */
+  function getElementId(element) {
+      var key = '_mduiEventId';
+      // @ts-ignore
+      if (!element[key]) {
+          // @ts-ignore
+          element[key] = ++mduiElementId;
+      }
+      // @ts-ignore
+      return element[key];
+  }
+  /**
+   * 解析事件名中的命名空间
+   */
+  function parse(type) {
+      var parts = type.split('.');
+      return {
+          type: parts[0],
+          ns: parts.slice(1).sort().join(' '),
+      };
+  }
+  /**
+   * 命名空间匹配规则
+   */
+  function matcherFor(ns) {
+      return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)');
+  }
+  /**
+   * 获取匹配的事件
+   * @param element
+   * @param type
+   * @param func
+   * @param selector
+   */
+  function getHandlers(element, type, func, selector) {
+      var event = parse(type);
+      return (handlers[getElementId(element)] || []).filter(function (handler) { return handler &&
+          (!event.type || handler.type === event.type) &&
+          (!event.ns || matcherFor(event.ns).test(handler.ns)) &&
+          (!func || getElementId(handler.func) === getElementId(func)) &&
+          (!selector || handler.selector === selector); });
+  }
+  /**
+   * 添加事件监听
+   * @param element
+   * @param types
+   * @param func
+   * @param data
+   * @param selector
+   */
+  function add(element, types, func, data, selector) {
+      var elementId = getElementId(element);
+      if (!handlers[elementId]) {
+          handlers[elementId] = [];
+      }
+      // 传入 data.useCapture 来设置 useCapture: true
+      var useCapture = false;
+      if (isObjectLike(data) && data.useCapture) {
+          useCapture = true;
+      }
+      types.split(' ').forEach(function (type) {
+          if (!type) {
+              return;
+          }
+          var event = parse(type);
+          function callFn(e, elem) {
+              // 因为鼠标事件模拟事件的 detail 属性是只读的,因此在 e._detail 中存储参数
+              var result = func.apply(elem, 
+              // @ts-ignore
+              e._detail === undefined ? [e] : [e].concat(e._detail));
+              if (result === false) {
+                  e.preventDefault();
+                  e.stopPropagation();
+              }
+          }
+          function proxyFn(e) {
+              // @ts-ignore
+              if (e._ns && !matcherFor(e._ns).test(event.ns)) {
+                  return;
+              }
+              // @ts-ignore
+              e._data = data;
+              if (selector) {
+                  // 事件代理
+                  $(element)
+                      .find(selector)
+                      .get()
+                      .reverse()
+                      .forEach(function (elem) {
+                      if (elem === e.target ||
+                          contains(elem, e.target)) {
+                          callFn(e, elem);
+                      }
+                  });
+              }
+              else {
+                  // 不使用事件代理
+                  callFn(e, element);
+              }
+          }
+          var handler = {
+              type: event.type,
+              ns: event.ns,
+              func: func,
+              selector: selector,
+              id: handlers[elementId].length,
+              proxy: proxyFn,
+          };
+          handlers[elementId].push(handler);
+          element.addEventListener(handler.type, proxyFn, useCapture);
+      });
+  }
+  /**
+   * 移除事件监听
+   * @param element
+   * @param types
+   * @param func
+   * @param selector
+   */
+  function remove(element, types, func, selector) {
+      var handlersInElement = handlers[getElementId(element)] || [];
+      var removeEvent = function (handler) {
+          delete handlersInElement[handler.id];
+          element.removeEventListener(handler.type, handler.proxy, false);
+      };
+      if (!types) {
+          handlersInElement.forEach(function (handler) { return removeEvent(handler); });
+      }
+      else {
+          types.split(' ').forEach(function (type) {
+              if (type) {
+                  getHandlers(element, type, func, selector).forEach(function (handler) { return removeEvent(handler); });
+              }
+          });
+      }
+  }
+
+  $.fn.trigger = function (type, extraParameters) {
+      var event = parse(type);
+      var eventObject;
+      var eventParams = {
+          bubbles: true,
+          cancelable: true,
+      };
+      var isMouseEvent = ['click', 'mousedown', 'mouseup', 'mousemove'].indexOf(event.type) > -1;
+      if (isMouseEvent) {
+          // Note: MouseEvent 无法传入 detail 参数
+          eventObject = new MouseEvent(event.type, eventParams);
+      }
+      else {
+          eventParams.detail = extraParameters;
+          eventObject = new CustomEvent(event.type, eventParams);
+      }
+      // @ts-ignore
+      eventObject._detail = extraParameters;
+      // @ts-ignore
+      eventObject._ns = event.ns;
+      return this.each(function () {
+          this.dispatchEvent(eventObject);
+      });
+  };
+
+  function extend(target, object1) {
+      var objectN = [], len = arguments.length - 2;
+      while ( len-- > 0 ) objectN[ len ] = arguments[ len + 2 ];
+
+      objectN.unshift(object1);
+      each(objectN, function (_, object) {
+          each(object, function (prop, value) {
+              if (!isUndefined(value)) {
+                  target[prop] = value;
+              }
+          });
+      });
+      return target;
+  }
+
+  /**
+   * 将数组或对象序列化,序列化后的字符串可作为 URL 查询字符串使用
+   *
+   * 若传入数组,则格式必须和 serializeArray 方法的返回值一样
+   * @param obj 对象或数组
+   * @example
+  ```js
+  param({ width: 1680, height: 1050 });
+  // width=1680&height=1050
+  ```
+   * @example
+  ```js
+  param({ foo: { one: 1, two: 2 }})
+  // foo[one]=1&foo[two]=2
+  ```
+   * @example
+  ```js
+  param({ids: [1, 2, 3]})
+  // ids[]=1&ids[]=2&ids[]=3
+  ```
+   * @example
+  ```js
+  param([
+    {"name":"name","value":"mdui"},
+    {"name":"password","value":"123456"}
+  ])
+  // name=mdui&password=123456
+  ```
+   */
+  function param(obj) {
+      if (!isObjectLike(obj) && !Array.isArray(obj)) {
+          return '';
+      }
+      var args = [];
+      function destructure(key, value) {
+          var keyTmp;
+          if (isObjectLike(value)) {
+              each(value, function (i, v) {
+                  if (Array.isArray(value) && !isObjectLike(v)) {
+                      keyTmp = '';
+                  }
+                  else {
+                      keyTmp = i;
+                  }
+                  destructure((key + "[" + keyTmp + "]"), v);
+              });
+          }
+          else {
+              if (value == null || value === '') {
+                  keyTmp = '=';
+              }
+              else {
+                  keyTmp = "=" + (encodeURIComponent(value));
+              }
+              args.push(encodeURIComponent(key) + keyTmp);
+          }
+      }
+      if (Array.isArray(obj)) {
+          each(obj, function () {
+              destructure(this.name, this.value);
+          });
+      }
+      else {
+          each(obj, destructure);
+      }
+      return args.join('&');
+  }
+
+  // 全局配置参数
+  var globalOptions = {};
+  // 全局事件名
+  var ajaxEvents = {
+      ajaxStart: 'start.mdui.ajax',
+      ajaxSuccess: 'success.mdui.ajax',
+      ajaxError: 'error.mdui.ajax',
+      ajaxComplete: 'complete.mdui.ajax',
+  };
+
+  /**
+   * 判断此请求方法是否通过查询字符串提交参数
+   * @param method 请求方法,大写
+   */
+  function isQueryStringData(method) {
+      return ['GET', 'HEAD'].indexOf(method) >= 0;
+  }
+  /**
+   * 添加参数到 URL 上,且 URL 中不存在 ? 时,自动把第一个 & 替换为 ?
+   * @param url
+   * @param query
+   */
+  function appendQuery(url, query) {
+      return (url + "&" + query).replace(/[&?]{1,2}/, '?');
+  }
+  /**
+   * 合并请求参数,参数优先级:options > globalOptions > defaults
+   * @param options
+   */
+  function mergeOptions(options) {
+      // 默认参数
+      var defaults = {
+          url: '',
+          method: 'GET',
+          data: '',
+          processData: true,
+          async: true,
+          cache: true,
+          username: '',
+          password: '',
+          headers: {},
+          xhrFields: {},
+          statusCode: {},
+          dataType: 'text',
+          contentType: 'application/x-www-form-urlencoded',
+          timeout: 0,
+          global: true,
+      };
+      // globalOptions 中的回调函数不合并
+      each(globalOptions, function (key, value) {
+          var callbacks = [
+              'beforeSend',
+              'success',
+              'error',
+              'complete',
+              'statusCode' ];
+          // @ts-ignore
+          if (callbacks.indexOf(key) < 0 && !isUndefined(value)) {
+              defaults[key] = value;
+          }
+      });
+      return extend({}, defaults, options);
+  }
+  /**
+   * 发送 ajax 请求
+   * @param options
+   * @example
+  ```js
+  ajax({
+    method: "POST",
+    url: "some.php",
+    data: { name: "John", location: "Boston" }
+  }).then(function( msg ) {
+    alert( "Data Saved: " + msg );
+  });
+  ```
+   */
+  function ajax(options) {
+      // 是否已取消请求
+      var isCanceled = false;
+      // 事件参数
+      var eventParams = {};
+      // 参数合并
+      var mergedOptions = mergeOptions(options);
+      var url = mergedOptions.url || window.location.toString();
+      var method = mergedOptions.method.toUpperCase();
+      var data = mergedOptions.data;
+      var processData = mergedOptions.processData;
+      var async = mergedOptions.async;
+      var cache = mergedOptions.cache;
+      var username = mergedOptions.username;
+      var password = mergedOptions.password;
+      var headers = mergedOptions.headers;
+      var xhrFields = mergedOptions.xhrFields;
+      var statusCode = mergedOptions.statusCode;
+      var dataType = mergedOptions.dataType;
+      var contentType = mergedOptions.contentType;
+      var timeout = mergedOptions.timeout;
+      var global = mergedOptions.global;
+      // 需要发送的数据
+      // GET/HEAD 请求和 processData 为 true 时,转换为查询字符串格式,特殊格式不转换
+      if (data &&
+          (isQueryStringData(method) || processData) &&
+          !isString(data) &&
+          !(data instanceof ArrayBuffer) &&
+          !(data instanceof Blob) &&
+          !(data instanceof Document) &&
+          !(data instanceof FormData)) {
+          data = param(data);
+      }
+      // 对于 GET、HEAD 类型的请求,把 data 数据添加到 URL 中
+      if (data && isQueryStringData(method)) {
+          // 查询字符串拼接到 URL 中
+          url = appendQuery(url, data);
+          data = null;
+      }
+      /**
+       * 触发事件和回调函数
+       * @param event
+       * @param params
+       * @param callback
+       * @param args
+       */
+      function trigger(event, params, callback) {
+          var args = [], len = arguments.length - 3;
+          while ( len-- > 0 ) args[ len ] = arguments[ len + 3 ];
+
+          // 触发全局事件
+          if (global) {
+              $(document).trigger(event, params);
+          }
+          // 触发 ajax 回调和事件
+          var result1;
+          var result2;
+          if (callback) {
+              // 全局回调
+              if (callback in globalOptions) {
+                  // @ts-ignore
+                  result1 = globalOptions[callback].apply(globalOptions, args);
+              }
+              // 自定义回调
+              if (mergedOptions[callback]) {
+                  // @ts-ignore
+                  result2 = mergedOptions[callback].apply(mergedOptions, args);
+              }
+              // beforeSend 回调返回 false 时取消 ajax 请求
+              if (callback === 'beforeSend' &&
+                  (result1 === false || result2 === false)) {
+                  isCanceled = true;
+              }
+          }
+      }
+      // XMLHttpRequest 请求
+      function XHR() {
+          var textStatus;
+          return new Promise(function (resolve, reject) {
+              // GET/HEAD 请求的缓存处理
+              if (isQueryStringData(method) && !cache) {
+                  url = appendQuery(url, ("_=" + (Date.now())));
+              }
+              // 创建 XHR
+              var xhr = new XMLHttpRequest();
+              xhr.open(method, url, async, username, password);
+              if (contentType ||
+                  (data && !isQueryStringData(method) && contentType !== false)) {
+                  xhr.setRequestHeader('Content-Type', contentType);
+              }
+              // 设置 Accept
+              if (dataType === 'json') {
+                  xhr.setRequestHeader('Accept', 'application/json, text/javascript');
+              }
+              // 添加 headers
+              if (headers) {
+                  each(headers, function (key, value) {
+                      // undefined 值不发送,string 和 null 需要发送
+                      if (!isUndefined(value)) {
+                          xhr.setRequestHeader(key, value + ''); // 把 null 转换成字符串
+                      }
+                  });
+              }
+              // 检查是否是跨域请求,跨域请求时不添加 X-Requested-With
+              var crossDomain = /^([\w-]+:)?\/\/([^/]+)/.test(url) &&
+                  RegExp.$2 !== window.location.host;
+              if (!crossDomain) {
+                  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+              }
+              if (xhrFields) {
+                  each(xhrFields, function (key, value) {
+                      // @ts-ignore
+                      xhr[key] = value;
+                  });
+              }
+              eventParams.xhr = xhr;
+              eventParams.options = mergedOptions;
+              var xhrTimeout;
+              xhr.onload = function () {
+                  if (xhrTimeout) {
+                      clearTimeout(xhrTimeout);
+                  }
+                  // AJAX 返回的 HTTP 响应码是否表示成功
+                  var isHttpStatusSuccess = (xhr.status >= 200 && xhr.status < 300) ||
+                      xhr.status === 304 ||
+                      xhr.status === 0;
+                  var responseData;
+                  if (isHttpStatusSuccess) {
+                      if (xhr.status === 204 || method === 'HEAD') {
+                          textStatus = 'nocontent';
+                      }
+                      else if (xhr.status === 304) {
+                          textStatus = 'notmodified';
+                      }
+                      else {
+                          textStatus = 'success';
+                      }
+                      if (dataType === 'json') {
+                          try {
+                              responseData =
+                                  method === 'HEAD' ? undefined : JSON.parse(xhr.responseText);
+                              eventParams.data = responseData;
+                          }
+                          catch (err) {
+                              textStatus = 'parsererror';
+                              trigger(ajaxEvents.ajaxError, eventParams, 'error', xhr, textStatus);
+                              reject(new Error(textStatus));
+                          }
+                          if (textStatus !== 'parsererror') {
+                              trigger(ajaxEvents.ajaxSuccess, eventParams, 'success', responseData, textStatus, xhr);
+                              resolve(responseData);
+                          }
+                      }
+                      else {
+                          responseData =
+                              method === 'HEAD'
+                                  ? undefined
+                                  : xhr.responseType === 'text' || xhr.responseType === ''
+                                      ? xhr.responseText
+                                      : xhr.response;
+                          eventParams.data = responseData;
+                          trigger(ajaxEvents.ajaxSuccess, eventParams, 'success', responseData, textStatus, xhr);
+                          resolve(responseData);
+                      }
+                  }
+                  else {
+                      textStatus = 'error';
+                      trigger(ajaxEvents.ajaxError, eventParams, 'error', xhr, textStatus);
+                      reject(new Error(textStatus));
+                  }
+                  // statusCode
+                  each([globalOptions.statusCode, statusCode], function (_, func) {
+                      if (func && func[xhr.status]) {
+                          if (isHttpStatusSuccess) {
+                              func[xhr.status](responseData, textStatus, xhr);
+                          }
+                          else {
+                              func[xhr.status](xhr, textStatus);
+                          }
+                      }
+                  });
+                  trigger(ajaxEvents.ajaxComplete, eventParams, 'complete', xhr, textStatus);
+              };
+              xhr.onerror = function () {
+                  if (xhrTimeout) {
+                      clearTimeout(xhrTimeout);
+                  }
+                  trigger(ajaxEvents.ajaxError, eventParams, 'error', xhr, xhr.statusText);
+                  trigger(ajaxEvents.ajaxComplete, eventParams, 'complete', xhr, 'error');
+                  reject(new Error(xhr.statusText));
+              };
+              xhr.onabort = function () {
+                  var statusText = 'abort';
+                  if (xhrTimeout) {
+                      statusText = 'timeout';
+                      clearTimeout(xhrTimeout);
+                  }
+                  trigger(ajaxEvents.ajaxError, eventParams, 'error', xhr, statusText);
+                  trigger(ajaxEvents.ajaxComplete, eventParams, 'complete', xhr, statusText);
+                  reject(new Error(statusText));
+              };
+              // ajax start 回调
+              trigger(ajaxEvents.ajaxStart, eventParams, 'beforeSend', xhr);
+              if (isCanceled) {
+                  reject(new Error('cancel'));
+                  return;
+              }
+              // Timeout
+              if (timeout > 0) {
+                  xhrTimeout = setTimeout(function () {
+                      xhr.abort();
+                  }, timeout);
+              }
+              // 发送 XHR
+              xhr.send(data);
+          });
+      }
+      return XHR();
+  }
+
+  $.ajax = ajax;
+
+  /**
+   * 为 Ajax 请求设置全局配置参数
+   * @param options 键值对参数
+   * @example
+  ```js
+  ajaxSetup({
+    dataType: 'json',
+    method: 'POST',
+  });
+  ```
+   */
+  function ajaxSetup(options) {
+      return extend(globalOptions, options);
+  }
+
+  $.ajaxSetup = ajaxSetup;
+
+  $.contains = contains;
+
+  var dataNS = '_mduiElementDataStorage';
+
+  /**
+   * 在元素上设置键值对数据
+   * @param element
+   * @param object
+   */
+  function setObjectToElement(element, object) {
+      // @ts-ignore
+      if (!element[dataNS]) {
+          // @ts-ignore
+          element[dataNS] = {};
+      }
+      each(object, function (key, value) {
+          // @ts-ignore
+          element[dataNS][toCamelCase(key)] = value;
+      });
+  }
+  function data(element, key, value) {
+      var obj;
+
+      // 根据键值对设置值
+      // data(element, { 'key' : 'value' })
+      if (isObjectLike(key)) {
+          setObjectToElement(element, key);
+          return key;
+      }
+      // 根据 key、value 设置值
+      // data(element, 'key', 'value')
+      if (!isUndefined(value)) {
+          setObjectToElement(element, ( obj = {}, obj[key] = value, obj ));
+          return value;
+      }
+      // 获取所有值
+      // data(element)
+      if (isUndefined(key)) {
+          // @ts-ignore
+          return element[dataNS] ? element[dataNS] : {};
+      }
+      // 从 dataNS 中获取指定值
+      // data(element, 'key')
+      key = toCamelCase(key);
+      // @ts-ignore
+      if (element[dataNS] && key in element[dataNS]) {
+          // @ts-ignore
+          return element[dataNS][key];
+      }
+      return undefined;
+  }
+
+  $.data = data;
+
+  $.each = each;
+
+  $.extend = function () {
+      var this$1 = this;
+      var objectN = [], len = arguments.length;
+      while ( len-- ) objectN[ len ] = arguments[ len ];
+
+      if (objectN.length === 1) {
+          each(objectN[0], function (prop, value) {
+              this$1[prop] = value;
+          });
+          return this;
+      }
+      return extend.apply(void 0, [ objectN.shift(), objectN.shift() ].concat( objectN ));
+  };
+
+  function map(elements, callback) {
+      var ref;
+
+      var value;
+      var ret = [];
+      each(elements, function (i, element) {
+          value = callback.call(window, element, i);
+          if (value != null) {
+              ret.push(value);
+          }
+      });
+      return (ref = []).concat.apply(ref, ret);
+  }
+
+  $.map = map;
+
+  $.merge = merge;
+
+  $.param = param;
+
+  /**
+   * 移除指定元素上存放的数据
+   * @param element 存放数据的元素
+   * @param name
+   * 数据键名
+   *
+   * 若未指定键名,将移除元素上所有数据
+   *
+   * 多个键名可以用空格分隔,或者用数组表示多个键名
+    @example
+  ```js
+  // 移除元素上键名为 name 的数据
+  removeData(document.body, 'name');
+  ```
+   * @example
+  ```js
+  // 移除元素上键名为 name1 和 name2 的数据
+  removeData(document.body, 'name1 name2');
+  ```
+   * @example
+  ```js
+  // 移除元素上键名为 name1 和 name2 的数据
+  removeData(document.body, ['name1', 'name2']);
+  ```
+   * @example
+  ```js
+  // 移除元素上所有数据
+  removeData(document.body);
+  ```
+   */
+  function removeData(element, name) {
+      // @ts-ignore
+      if (!element[dataNS]) {
+          return;
+      }
+      var remove = function (nameItem) {
+          nameItem = toCamelCase(nameItem);
+          // @ts-ignore
+          if (element[dataNS][nameItem]) {
+              // @ts-ignore
+              element[dataNS][nameItem] = null;
+              // @ts-ignore
+              delete element[dataNS][nameItem];
+          }
+      };
+      if (isUndefined(name)) {
+          // @ts-ignore
+          element[dataNS] = null;
+          // @ts-ignore
+          delete element[dataNS];
+          // @ts-ignore
+      }
+      else if (isString(name)) {
+          name
+              .split(' ')
+              .filter(function (nameItem) { return nameItem; })
+              .forEach(function (nameItem) { return remove(nameItem); });
+      }
+      else {
+          each(name, function (_, nameItem) { return remove(nameItem); });
+      }
+  }
+
+  $.removeData = removeData;
+
+  /**
+   * 过滤掉数组中的重复元素
+   * @param arr 数组
+   * @example
+  ```js
+  unique([1, 2, 12, 3, 2, 1, 2, 1, 1]);
+  // [1, 2, 12, 3]
+  ```
+   */
+  function unique(arr) {
+      var result = [];
+      each(arr, function (_, val) {
+          if (result.indexOf(val) === -1) {
+              result.push(val);
+          }
+      });
+      return result;
+  }
+
+  $.unique = unique;
+
+  $.fn.add = function (selector) {
+      return new JQ(unique(merge(this.get(), $(selector).get())));
+  };
+
+  each(['add', 'remove', 'toggle'], function (_, name) {
+      $.fn[(name + "Class")] = function (className) {
+          if (name === 'remove' && !arguments.length) {
+              return this.each(function (_, element) {
+                  element.setAttribute('class', '');
+              });
+          }
+          return this.each(function (i, element) {
+              if (!isElement(element)) {
+                  return;
+              }
+              var classes = (isFunction(className)
+                  ? className.call(element, i, element.getAttribute('class') || '')
+                  : className)
+                  .split(' ')
+                  .filter(function (name) { return name; });
+              each(classes, function (_, cls) {
+                  element.classList[name](cls);
+              });
+          });
+      };
+  });
+
+  each(['insertBefore', 'insertAfter'], function (nameIndex, name) {
+      $.fn[name] = function (target) {
+          var $element = nameIndex ? $(this.get().reverse()) : this; // 顺序和 jQuery 保持一致
+          var $target = $(target);
+          var result = [];
+          $target.each(function (index, target) {
+              if (!target.parentNode) {
+                  return;
+              }
+              $element.each(function (_, element) {
+                  var newItem = index
+                      ? element.cloneNode(true)
+                      : element;
+                  var existingItem = nameIndex ? target.nextSibling : target;
+                  result.push(newItem);
+                  target.parentNode.insertBefore(newItem, existingItem);
+              });
+          });
+          return $(nameIndex ? result.reverse() : result);
+      };
+  });
+
+  /**
+   * 是否不是 HTML 字符串(包裹在 <> 中)
+   * @param target
+   */
+  function isPlainText(target) {
+      return (isString(target) && (target[0] !== '<' || target[target.length - 1] !== '>'));
+  }
+  each(['before', 'after'], function (nameIndex, name) {
+      $.fn[name] = function () {
+          var args = [], len = arguments.length;
+          while ( len-- ) args[ len ] = arguments[ len ];
+
+          // after 方法,多个参数需要按参数顺序添加到元素后面,所以需要将参数顺序反向处理
+          if (nameIndex === 1) {
+              args = args.reverse();
+          }
+          return this.each(function (index, element) {
+              var targets = isFunction(args[0])
+                  ? [args[0].call(element, index, element.innerHTML)]
+                  : args;
+              each(targets, function (_, target) {
+                  var $target;
+                  if (isPlainText(target)) {
+                      $target = $(getChildNodesArray(target, 'div'));
+                  }
+                  else if (index && isElement(target)) {
+                      $target = $(target.cloneNode(true));
+                  }
+                  else {
+                      $target = $(target);
+                  }
+                  $target[nameIndex ? 'insertAfter' : 'insertBefore'](element);
+              });
+          });
+      };
+  });
+
+  $.fn.off = function (types, selector, callback) {
+      var this$1 = this;
+
+      // types 是对象
+      if (isObjectLike(types)) {
+          each(types, function (type, fn) {
+              // this.off('click', undefined, function () {})
+              // this.off('click', '.box', function () {})
+              this$1.off(type, selector, fn);
+          });
+          return this;
+      }
+      // selector 不存在
+      if (selector === false || isFunction(selector)) {
+          callback = selector;
+          selector = undefined;
+          // this.off('click', undefined, function () {})
+      }
+      // callback 传入 `false`,相当于 `return false`
+      if (callback === false) {
+          callback = returnFalse;
+      }
+      return this.each(function () {
+          remove(this, types, callback, selector);
+      });
+  };
+
+  $.fn.on = function (types, selector, data, callback, one) {
+      var this$1 = this;
+
+      // types 可以是 type/func 对象
+      if (isObjectLike(types)) {
+          // (types-Object, selector, data)
+          if (!isString(selector)) {
+              // (types-Object, data)
+              data = data || selector;
+              selector = undefined;
+          }
+          each(types, function (type, fn) {
+              // selector 和 data 都可能是 undefined
+              // @ts-ignore
+              this$1.on(type, selector, data, fn, one);
+          });
+          return this;
+      }
+      if (data == null && callback == null) {
+          // (types, fn)
+          callback = selector;
+          data = selector = undefined;
+      }
+      else if (callback == null) {
+          if (isString(selector)) {
+              // (types, selector, fn)
+              callback = data;
+              data = undefined;
+          }
+          else {
+              // (types, data, fn)
+              callback = data;
+              data = selector;
+              selector = undefined;
+          }
+      }
+      if (callback === false) {
+          callback = returnFalse;
+      }
+      else if (!callback) {
+          return this;
+      }
+      // $().one()
+      if (one) {
+          // eslint-disable-next-line @typescript-eslint/no-this-alias
+          var _this = this;
+          var origCallback = callback;
+          callback = function (event) {
+              _this.off(event.type, selector, callback);
+              // eslint-disable-next-line prefer-rest-params
+              return origCallback.apply(this, arguments);
+          };
+      }
+      return this.each(function () {
+          add(this, types, callback, data, selector);
+      });
+  };
+
+  each(ajaxEvents, function (name, eventName) {
+      $.fn[name] = function (fn) {
+          return this.on(eventName, function (e, params) {
+              fn(e, params.xhr, params.options, params.data);
+          });
+      };
+  });
+
+  $.fn.map = function (callback) {
+      return new JQ(map(this, function (element, i) { return callback.call(element, i, element); }));
+  };
+
+  $.fn.clone = function () {
+      return this.map(function () {
+          return this.cloneNode(true);
+      });
+  };
+
+  $.fn.is = function (selector) {
+      var isMatched = false;
+      if (isFunction(selector)) {
+          this.each(function (index, element) {
+              if (selector.call(element, index, element)) {
+                  isMatched = true;
+              }
+          });
+          return isMatched;
+      }
+      if (isString(selector)) {
+          this.each(function (_, element) {
+              if (isDocument(element) || isWindow(element)) {
+                  return;
+              }
+              // @ts-ignore
+              var matches = element.matches || element.msMatchesSelector;
+              if (matches.call(element, selector)) {
+                  isMatched = true;
+              }
+          });
+          return isMatched;
+      }
+      var $compareWith = $(selector);
+      this.each(function (_, element) {
+          $compareWith.each(function (_, compare) {
+              if (element === compare) {
+                  isMatched = true;
+              }
+          });
+      });
+      return isMatched;
+  };
+
+  $.fn.remove = function (selector) {
+      return this.each(function (_, element) {
+          if (element.parentNode && (!selector || $(element).is(selector))) {
+              element.parentNode.removeChild(element);
+          }
+      });
+  };
+
+  each(['prepend', 'append'], function (nameIndex, name) {
+      $.fn[name] = function () {
+          var args = [], len = arguments.length;
+          while ( len-- ) args[ len ] = arguments[ len ];
+
+          return this.each(function (index, element) {
+              var ref;
+
+              var childNodes = element.childNodes;
+              var childLength = childNodes.length;
+              var child = childLength
+                  ? childNodes[nameIndex ? childLength - 1 : 0]
+                  : document.createElement('div');
+              if (!childLength) {
+                  element.appendChild(child);
+              }
+              var contents = isFunction(args[0])
+                  ? [args[0].call(element, index, element.innerHTML)]
+                  : args;
+              // 如果不是字符串,则仅第一个元素使用原始元素,其他的都克隆自第一个元素
+              if (index) {
+                  contents = contents.map(function (content) {
+                      return isString(content) ? content : $(content).clone();
+                  });
+              }
+              (ref = $(child))[nameIndex ? 'after' : 'before'].apply(ref, contents);
+              if (!childLength) {
+                  element.removeChild(child);
+              }
+          });
+      };
+  });
+
+  each(['appendTo', 'prependTo'], function (nameIndex, name) {
+      $.fn[name] = function (target) {
+          var extraChilds = [];
+          var $target = $(target).map(function (_, element) {
+              var childNodes = element.childNodes;
+              var childLength = childNodes.length;
+              if (childLength) {
+                  return childNodes[nameIndex ? 0 : childLength - 1];
+              }
+              var child = document.createElement('div');
+              element.appendChild(child);
+              extraChilds.push(child);
+              return child;
+          });
+          var $result = this[nameIndex ? 'insertBefore' : 'insertAfter']($target);
+          $(extraChilds).remove();
+          return $result;
+      };
+  });
+
+  each(['attr', 'prop', 'css'], function (nameIndex, name) {
+      function set(element, key, value) {
+          // 值为 undefined 时,不修改
+          if (isUndefined(value)) {
+              return;
+          }
+          switch (nameIndex) {
+              // attr
+              case 0:
+                  if (isNull(value)) {
+                      element.removeAttribute(key);
+                  }
+                  else {
+                      element.setAttribute(key, value);
+                  }
+                  break;
+              // prop
+              case 1:
+                  // @ts-ignore
+                  element[key] = value;
+                  break;
+              // css
+              default:
+                  key = toCamelCase(key);
+                  // @ts-ignore
+                  element.style[key] = isNumber(value)
+                      ? ("" + value + (cssNumber.indexOf(key) > -1 ? '' : 'px'))
+                      : value;
+                  break;
+          }
+      }
+      function get(element, key) {
+          switch (nameIndex) {
+              // attr
+              case 0:
+                  // 属性不存在时,原生 getAttribute 方法返回 null,而 jquery 返回 undefined。这里和 jquery 保持一致
+                  var value = element.getAttribute(key);
+                  return isNull(value) ? undefined : value;
+              // prop
+              case 1:
+                  // @ts-ignore
+                  return element[key];
+              // css
+              default:
+                  return getStyle(element, key);
+          }
+      }
+      $.fn[name] = function (key, value) {
+          var this$1 = this;
+
+          if (isObjectLike(key)) {
+              each(key, function (k, v) {
+                  // @ts-ignore
+                  this$1[name](k, v);
+              });
+              return this;
+          }
+          if (arguments.length === 1) {
+              var element = this[0];
+              return isElement(element) ? get(element, key) : undefined;
+          }
+          return this.each(function (i, element) {
+              set(element, key, isFunction(value) ? value.call(element, i, get(element, key)) : value);
+          });
+      };
+  });
+
+  $.fn.children = function (selector) {
+      var children = [];
+      this.each(function (_, element) {
+          each(element.childNodes, function (__, childNode) {
+              if (!isElement(childNode)) {
+                  return;
+              }
+              if (!selector || $(childNode).is(selector)) {
+                  children.push(childNode);
+              }
+          });
+      });
+      return new JQ(unique(children));
+  };
+
+  $.fn.slice = function () {
+      var args = [], len = arguments.length;
+      while ( len-- ) args[ len ] = arguments[ len ];
+
+      return new JQ([].slice.apply(this, args));
+  };
+
+  $.fn.eq = function (index) {
+      var ret = index === -1 ? this.slice(index) : this.slice(index, +index + 1);
+      return new JQ(ret);
+  };
+
+  function dir($elements, nameIndex, node, selector, filter) {
+      var ret = [];
+      var target;
+      $elements.each(function (_, element) {
+          target = element[node];
+          // 不能包含最顶层的 document 元素
+          while (target && isElement(target)) {
+              // prevUntil, nextUntil, parentsUntil
+              if (nameIndex === 2) {
+                  if (selector && $(target).is(selector)) {
+                      break;
+                  }
+                  if (!filter || $(target).is(filter)) {
+                      ret.push(target);
+                  }
+              }
+              // prev, next, parent
+              else if (nameIndex === 0) {
+                  if (!selector || $(target).is(selector)) {
+                      ret.push(target);
+                  }
+                  break;
+              }
+              // prevAll, nextAll, parents
+              else {
+                  if (!selector || $(target).is(selector)) {
+                      ret.push(target);
+                  }
+              }
+              // @ts-ignore
+              target = target[node];
+          }
+      });
+      return new JQ(unique(ret));
+  }
+
+  each(['', 's', 'sUntil'], function (nameIndex, name) {
+      $.fn[("parent" + name)] = function (selector, filter) {
+          // parents、parentsUntil 需要把元素的顺序反向处理,以便和 jQuery 的结果一致
+          var $nodes = !nameIndex ? this : $(this.get().reverse());
+          return dir($nodes, nameIndex, 'parentNode', selector, filter);
+      };
+  });
+
+  $.fn.closest = function (selector) {
+      if (this.is(selector)) {
+          return this;
+      }
+      var matched = [];
+      this.parents().each(function (_, element) {
+          if ($(element).is(selector)) {
+              matched.push(element);
+              return false;
+          }
+      });
+      return new JQ(matched);
+  };
+
+  var rbrace = /^(?:{[\w\W]*\}|\[[\w\W]*\])$/;
+  // 从 `data-*` 中获取的值,需要经过该函数转换
+  function getData(value) {
+      if (value === 'true') {
+          return true;
+      }
+      if (value === 'false') {
+          return false;
+      }
+      if (value === 'null') {
+          return null;
+      }
+      if (value === +value + '') {
+          return +value;
+      }
+      if (rbrace.test(value)) {
+          return JSON.parse(value);
+      }
+      return value;
+  }
+  // 若 value 不存在,则从 `data-*` 中获取值
+  function dataAttr(element, key, value) {
+      if (isUndefined(value) && element.nodeType === 1) {
+          var name = 'data-' + toKebabCase(key);
+          value = element.getAttribute(name);
+          if (isString(value)) {
+              try {
+                  value = getData(value);
+              }
+              catch (e) { }
+          }
+          else {
+              value = undefined;
+          }
+      }
+      return value;
+  }
+  $.fn.data = function (key, value) {
+      // 获取所有值
+      if (isUndefined(key)) {
+          if (!this.length) {
+              return undefined;
+          }
+          var element = this[0];
+          var resultData = data(element);
+          // window, document 上不存在 `data-*` 属性
+          if (element.nodeType !== 1) {
+              return resultData;
+          }
+          // 从 `data-*` 中获取值
+          var attrs = element.attributes;
+          var i = attrs.length;
+          while (i--) {
+              if (attrs[i]) {
+                  var name = attrs[i].name;
+                  if (name.indexOf('data-') === 0) {
+                      name = toCamelCase(name.slice(5));
+                      resultData[name] = dataAttr(element, name, resultData[name]);
+                  }
+              }
+          }
+          return resultData;
+      }
+      // 同时设置多个值
+      if (isObjectLike(key)) {
+          return this.each(function () {
+              data(this, key);
+          });
+      }
+      // value 传入了 undefined
+      if (arguments.length === 2 && isUndefined(value)) {
+          return this;
+      }
+      // 设置值
+      if (!isUndefined(value)) {
+          return this.each(function () {
+              data(this, key, value);
+          });
+      }
+      // 获取值
+      if (!this.length) {
+          return undefined;
+      }
+      return dataAttr(this[0], key, data(this[0], key));
+  };
+
+  $.fn.empty = function () {
+      return this.each(function () {
+          this.innerHTML = '';
+      });
+  };
+
+  $.fn.extend = function (obj) {
+      each(obj, function (prop, value) {
+          // 在 JQ 对象上扩展方法时,需要自己添加 typescript 的类型定义
+          $.fn[prop] = value;
+      });
+      return this;
+  };
+
+  $.fn.filter = function (selector) {
+      if (isFunction(selector)) {
+          return this.map(function (index, element) { return selector.call(element, index, element) ? element : undefined; });
+      }
+      if (isString(selector)) {
+          return this.map(function (_, element) { return $(element).is(selector) ? element : undefined; });
+      }
+      var $selector = $(selector);
+      return this.map(function (_, element) { return $selector.get().indexOf(element) > -1 ? element : undefined; });
+  };
+
+  $.fn.first = function () {
+      return this.eq(0);
+  };
+
+  $.fn.has = function (selector) {
+      var $targets = isString(selector) ? this.find(selector) : $(selector);
+      var length = $targets.length;
+      return this.map(function () {
+          for (var i = 0; i < length; i += 1) {
+              if (contains(this, $targets[i])) {
+                  return this;
+              }
+          }
+          return;
+      });
+  };
+
+  $.fn.hasClass = function (className) {
+      return this[0].classList.contains(className);
+  };
+
+  /**
+   * 值上面的 padding、border、margin 处理
+   * @param element
+   * @param name
+   * @param value
+   * @param funcIndex
+   * @param includeMargin
+   * @param multiply
+   */
+  function handleExtraWidth(element, name, value, funcIndex, includeMargin, multiply) {
+      // 获取元素的 padding, border, margin 宽度(两侧宽度的和)
+      var getExtraWidthValue = function (extra) {
+          return (getExtraWidth(element, name.toLowerCase(), extra) *
+              multiply);
+      };
+      if (funcIndex === 2 && includeMargin) {
+          value += getExtraWidthValue('margin');
+      }
+      if (isBorderBox(element)) {
+          // IE 为 box-sizing: border-box 时,得到的值不含 border 和 padding,这里先修复
+          // 仅获取时需要处理,multiply === 1 为 get
+          if (isIE() && multiply === 1) {
+              value += getExtraWidthValue('border');
+              value += getExtraWidthValue('padding');
+          }
+          if (funcIndex === 0) {
+              value -= getExtraWidthValue('border');
+          }
+          if (funcIndex === 1) {
+              value -= getExtraWidthValue('border');
+              value -= getExtraWidthValue('padding');
+          }
+      }
+      else {
+          if (funcIndex === 0) {
+              value += getExtraWidthValue('padding');
+          }
+          if (funcIndex === 2) {
+              value += getExtraWidthValue('border');
+              value += getExtraWidthValue('padding');
+          }
+      }
+      return value;
+  }
+  /**
+   * 获取元素的样式值
+   * @param element
+   * @param name
+   * @param funcIndex 0: innerWidth, innerHeight; 1: width, height; 2: outerWidth, outerHeight
+   * @param includeMargin
+   */
+  function get(element, name, funcIndex, includeMargin) {
+      var clientProp = "client" + name;
+      var scrollProp = "scroll" + name;
+      var offsetProp = "offset" + name;
+      var innerProp = "inner" + name;
+      // $(window).width()
+      if (isWindow(element)) {
+          // outerWidth, outerHeight 需要包含滚动条的宽度
+          return funcIndex === 2
+              ? element[innerProp]
+              : toElement(document)[clientProp];
+      }
+      // $(document).width()
+      if (isDocument(element)) {
+          var doc = toElement(element);
+          return Math.max(
+          // @ts-ignore
+          element.body[scrollProp], doc[scrollProp], 
+          // @ts-ignore
+          element.body[offsetProp], doc[offsetProp], doc[clientProp]);
+      }
+      var value = parseFloat(getComputedStyleValue(element, name.toLowerCase()) || '0');
+      return handleExtraWidth(element, name, value, funcIndex, includeMargin, 1);
+  }
+  /**
+   * 设置元素的样式值
+   * @param element
+   * @param elementIndex
+   * @param name
+   * @param funcIndex 0: innerWidth, innerHeight; 1: width, height; 2: outerWidth, outerHeight
+   * @param includeMargin
+   * @param value
+   */
+  function set(element, elementIndex, name, funcIndex, includeMargin, value) {
+      var computedValue = isFunction(value)
+          ? value.call(element, elementIndex, get(element, name, funcIndex, includeMargin))
+          : value;
+      if (computedValue == null) {
+          return;
+      }
+      var $element = $(element);
+      var dimension = name.toLowerCase();
+      // 特殊的值,不需要计算 padding、border、margin
+      if (['auto', 'inherit', ''].indexOf(computedValue) > -1) {
+          $element.css(dimension, computedValue);
+          return;
+      }
+      // 其他值保留原始单位。注意:如果不使用 px 作为单位,则算出的值一般是不准确的
+      var suffix = computedValue.toString().replace(/\b[0-9.]*/, '');
+      var numerical = parseFloat(computedValue);
+      computedValue =
+          handleExtraWidth(element, name, numerical, funcIndex, includeMargin, -1) +
+              (suffix || 'px');
+      $element.css(dimension, computedValue);
+  }
+  each(['Width', 'Height'], function (_, name) {
+      each([("inner" + name), name.toLowerCase(), ("outer" + name)], function (funcIndex, funcName) {
+          $.fn[funcName] = function (margin, value) {
+              // 是否是赋值操作
+              var isSet = arguments.length && (funcIndex < 2 || !isBoolean(margin));
+              var includeMargin = margin === true || value === true;
+              // 获取第一个元素的值
+              if (!isSet) {
+                  return this.length
+                      ? get(this[0], name, funcIndex, includeMargin)
+                      : undefined;
+              }
+              // 设置每个元素的值
+              return this.each(function (index, element) { return set(element, index, name, funcIndex, includeMargin, margin); });
+          };
+      });
+  });
+
+  $.fn.hide = function () {
+      return this.each(function () {
+          this.style.display = 'none';
+      });
+  };
+
+  each(['val', 'html', 'text'], function (nameIndex, name) {
+      var props = {
+          0: 'value',
+          1: 'innerHTML',
+          2: 'textContent',
+      };
+      var propName = props[nameIndex];
+      function get($elements) {
+          // text() 获取所有元素的文本
+          if (nameIndex === 2) {
+              // @ts-ignore
+              return map($elements, function (element) { return toElement(element)[propName]; }).join('');
+          }
+          // 空集合时,val() 和 html() 返回 undefined
+          if (!$elements.length) {
+              return undefined;
+          }
+          // val() 和 html() 仅获取第一个元素的内容
+          var firstElement = $elements[0];
+          // select multiple 返回数组
+          if (nameIndex === 0 && $(firstElement).is('select[multiple]')) {
+              return map($(firstElement).find('option:checked'), function (element) { return element.value; });
+          }
+          // @ts-ignore
+          return firstElement[propName];
+      }
+      function set(element, value) {
+          // text() 和 html() 赋值为 undefined,则保持原内容不变
+          // val() 赋值为 undefined 则赋值为空
+          if (isUndefined(value)) {
+              if (nameIndex !== 0) {
+                  return;
+              }
+              value = '';
+          }
+          if (nameIndex === 1 && isElement(value)) {
+              value = value.outerHTML;
+          }
+          // @ts-ignore
+          element[propName] = value;
+      }
+      $.fn[name] = function (value) {
+          // 获取值
+          if (!arguments.length) {
+              return get(this);
+          }
+          // 设置值
+          return this.each(function (i, element) {
+              var computedValue = isFunction(value)
+                  ? value.call(element, i, get($(element)))
+                  : value;
+              // value 是数组,则选中数组中的元素,反选不在数组中的元素
+              if (nameIndex === 0 && Array.isArray(computedValue)) {
+                  // select[multiple]
+                  if ($(element).is('select[multiple]')) {
+                      map($(element).find('option'), function (option) { return (option.selected =
+                          computedValue.indexOf(option.value) >
+                              -1); });
+                  }
+                  // 其他 checkbox, radio 等元素
+                  else {
+                      element.checked =
+                          computedValue.indexOf(element.value) > -1;
+                  }
+              }
+              else {
+                  set(element, computedValue);
+              }
+          });
+      };
+  });
+
+  $.fn.index = function (selector) {
+      if (!arguments.length) {
+          return this.eq(0).parent().children().get().indexOf(this[0]);
+      }
+      if (isString(selector)) {
+          return $(selector).get().indexOf(this[0]);
+      }
+      return this.get().indexOf($(selector)[0]);
+  };
+
+  $.fn.last = function () {
+      return this.eq(-1);
+  };
+
+  each(['', 'All', 'Until'], function (nameIndex, name) {
+      $.fn[("next" + name)] = function (selector, filter) {
+          return dir(this, nameIndex, 'nextElementSibling', selector, filter);
+      };
+  });
+
+  $.fn.not = function (selector) {
+      var $excludes = this.filter(selector);
+      return this.map(function (_, element) { return $excludes.index(element) > -1 ? undefined : element; });
+  };
+
+  /**
+   * 返回最近的用于定位的父元素
+   */
+  $.fn.offsetParent = function () {
+      return this.map(function () {
+          var offsetParent = this.offsetParent;
+          while (offsetParent && $(offsetParent).css('position') === 'static') {
+              offsetParent = offsetParent.offsetParent;
+          }
+          return offsetParent || document.documentElement;
+      });
+  };
+
+  function floatStyle($element, name) {
+      return parseFloat($element.css(name));
+  }
+  $.fn.position = function () {
+      if (!this.length) {
+          return undefined;
+      }
+      var $element = this.eq(0);
+      var currentOffset;
+      var parentOffset = {
+          left: 0,
+          top: 0,
+      };
+      if ($element.css('position') === 'fixed') {
+          currentOffset = $element[0].getBoundingClientRect();
+      }
+      else {
+          currentOffset = $element.offset();
+          var $offsetParent = $element.offsetParent();
+          parentOffset = $offsetParent.offset();
+          parentOffset.top += floatStyle($offsetParent, 'border-top-width');
+          parentOffset.left += floatStyle($offsetParent, 'border-left-width');
+      }
+      return {
+          top: currentOffset.top - parentOffset.top - floatStyle($element, 'margin-top'),
+          left: currentOffset.left -
+              parentOffset.left -
+              floatStyle($element, 'margin-left'),
+      };
+  };
+
+  function get$1(element) {
+      if (!element.getClientRects().length) {
+          return { top: 0, left: 0 };
+      }
+      var rect = element.getBoundingClientRect();
+      var win = element.ownerDocument.defaultView;
+      return {
+          top: rect.top + win.pageYOffset,
+          left: rect.left + win.pageXOffset,
+      };
+  }
+  function set$1(element, value, index) {
+      var $element = $(element);
+      var position = $element.css('position');
+      if (position === 'static') {
+          $element.css('position', 'relative');
+      }
+      var currentOffset = get$1(element);
+      var currentTopString = $element.css('top');
+      var currentLeftString = $element.css('left');
+      var currentTop;
+      var currentLeft;
+      var calculatePosition = (position === 'absolute' || position === 'fixed') &&
+          (currentTopString + currentLeftString).indexOf('auto') > -1;
+      if (calculatePosition) {
+          var currentPosition = $element.position();
+          currentTop = currentPosition.top;
+          currentLeft = currentPosition.left;
+      }
+      else {
+          currentTop = parseFloat(currentTopString);
+          currentLeft = parseFloat(currentLeftString);
+      }
+      var computedValue = isFunction(value)
+          ? value.call(element, index, extend({}, currentOffset))
+          : value;
+      $element.css({
+          top: computedValue.top != null
+              ? computedValue.top - currentOffset.top + currentTop
+              : undefined,
+          left: computedValue.left != null
+              ? computedValue.left - currentOffset.left + currentLeft
+              : undefined,
+      });
+  }
+  $.fn.offset = function (value) {
+      // 获取坐标
+      if (!arguments.length) {
+          if (!this.length) {
+              return undefined;
+          }
+          return get$1(this[0]);
+      }
+      // 设置坐标
+      return this.each(function (index) {
+          set$1(this, value, index);
+      });
+  };
+
+  $.fn.one = function (types, selector, data, callback) {
+      // @ts-ignore
+      return this.on(types, selector, data, callback, true);
+  };
+
+  each(['', 'All', 'Until'], function (nameIndex, name) {
+      $.fn[("prev" + name)] = function (selector, filter) {
+          // prevAll、prevUntil 需要把元素的顺序倒序处理,以便和 jQuery 的结果一致
+          var $nodes = !nameIndex ? this : $(this.get().reverse());
+          return dir($nodes, nameIndex, 'previousElementSibling', selector, filter);
+      };
+  });
+
+  $.fn.removeAttr = function (attributeName) {
+      var names = attributeName.split(' ').filter(function (name) { return name; });
+      return this.each(function () {
+          var this$1 = this;
+
+          each(names, function (_, name) {
+              this$1.removeAttribute(name);
+          });
+      });
+  };
+
+  $.fn.removeData = function (name) {
+      return this.each(function () {
+          removeData(this, name);
+      });
+  };
+
+  $.fn.removeProp = function (name) {
+      return this.each(function () {
+          try {
+              // @ts-ignore
+              delete this[name];
+          }
+          catch (e) { }
+      });
+  };
+
+  $.fn.replaceWith = function (newContent) {
+      this.each(function (index, element) {
+          var content = newContent;
+          if (isFunction(content)) {
+              content = content.call(element, index, element.innerHTML);
+          }
+          else if (index && !isString(content)) {
+              content = $(content).clone();
+          }
+          $(element).before(content);
+      });
+      return this.remove();
+  };
+
+  $.fn.replaceAll = function (target) {
+      var this$1 = this;
+
+      return $(target).map(function (index, element) {
+          $(element).replaceWith(index ? this$1.clone() : this$1);
+          return this$1.get();
+      });
+  };
+
+  /**
+   * 将表单元素的值组合成键值对数组
+   * @returns {Array}
+   */
+  $.fn.serializeArray = function () {
+      var result = [];
+      this.each(function (_, element) {
+          var elements = element instanceof HTMLFormElement ? element.elements : [element];
+          $(elements).each(function (_, element) {
+              var $element = $(element);
+              var type = element.type;
+              var nodeName = element.nodeName.toLowerCase();
+              if (nodeName !== 'fieldset' &&
+                  element.name &&
+                  !element.disabled &&
+                  ['input', 'select', 'textarea', 'keygen'].indexOf(nodeName) > -1 &&
+                  ['submit', 'button', 'image', 'reset', 'file'].indexOf(type) === -1 &&
+                  (['radio', 'checkbox'].indexOf(type) === -1 ||
+                      element.checked)) {
+                  var value = $element.val();
+                  var valueArr = Array.isArray(value) ? value : [value];
+                  valueArr.forEach(function (value) {
+                      result.push({
+                          name: element.name,
+                          value: value,
+                      });
+                  });
+              }
+          });
+      });
+      return result;
+  };
+
+  $.fn.serialize = function () {
+      return param(this.serializeArray());
+  };
+
+  var elementDisplay = {};
+  /**
+   * 获取元素的初始 display 值,用于 .show() 方法
+   * @param nodeName
+   */
+  function defaultDisplay(nodeName) {
+      var element;
+      var display;
+      if (!elementDisplay[nodeName]) {
+          element = document.createElement(nodeName);
+          document.body.appendChild(element);
+          display = getStyle(element, 'display');
+          element.parentNode.removeChild(element);
+          if (display === 'none') {
+              display = 'block';
+          }
+          elementDisplay[nodeName] = display;
+      }
+      return elementDisplay[nodeName];
+  }
+  /**
+   * 显示指定元素
+   * @returns {JQ}
+   */
+  $.fn.show = function () {
+      return this.each(function () {
+          if (this.style.display === 'none') {
+              this.style.display = '';
+          }
+          if (getStyle(this, 'display') === 'none') {
+              this.style.display = defaultDisplay(this.nodeName);
+          }
+      });
+  };
+
+  /**
+   * 取得同辈元素的集合
+   * @param selector {String=}
+   * @returns {JQ}
+   */
+  $.fn.siblings = function (selector) {
+      return this.prevAll(selector).add(this.nextAll(selector));
+  };
+
+  /**
+   * 切换元素的显示状态
+   */
+  $.fn.toggle = function () {
+      return this.each(function () {
+          getStyle(this, 'display') === 'none' ? $(this).show() : $(this).hide();
+      });
+  };
+
+  $.fn.reflow = function () {
+      return this.each(function () {
+          return this.clientLeft;
+      });
+  };
+
+  $.fn.transition = function (duration) {
+      if (isNumber(duration)) {
+          duration = duration + "ms";
+      }
+      return this.each(function () {
+          this.style.webkitTransitionDuration = duration;
+          this.style.transitionDuration = duration;
+      });
+  };
+
+  $.fn.transitionEnd = function (callback) {
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      var that = this;
+      var events = ['webkitTransitionEnd', 'transitionend'];
+      function fireCallback(e) {
+          if (e.target !== this) {
+              return;
+          }
+          // @ts-ignore
+          callback.call(this, e);
+          each(events, function (_, event) {
+              that.off(event, fireCallback);
+          });
+      }
+      each(events, function (_, event) {
+          that.on(event, fireCallback);
+      });
+      return this;
+  };
+
+  $.fn.transformOrigin = function (transformOrigin) {
+      return this.each(function () {
+          this.style.webkitTransformOrigin = transformOrigin;
+          this.style.transformOrigin = transformOrigin;
+      });
+  };
+
+  $.fn.transform = function (transform) {
+      return this.each(function () {
+          this.style.webkitTransform = transform;
+          this.style.transform = transform;
+      });
+  };
+
+  /**
+   * CSS 选择器和初始化函数组成的对象
+   */
+  var entries = {};
+  /**
+   * 注册并执行初始化函数
+   * @param selector CSS 选择器
+   * @param apiInit 初始化函数
+   * @param i 元素索引
+   * @param element 元素
+   */
+  function mutation(selector, apiInit, i, element) {
+      var selectors = data(element, '_mdui_mutation');
+      if (!selectors) {
+          selectors = [];
+          data(element, '_mdui_mutation', selectors);
+      }
+      if (selectors.indexOf(selector) === -1) {
+          selectors.push(selector);
+          apiInit.call(element, i, element);
+      }
+  }
+
+  $.fn.mutation = function () {
+      return this.each(function (i, element) {
+          var $this = $(element);
+          each(entries, function (selector, apiInit) {
+              if ($this.is(selector)) {
+                  mutation(selector, apiInit, i, element);
+              }
+              $this.find(selector).each(function (i, element) {
+                  mutation(selector, apiInit, i, element);
+              });
+          });
+      });
+  };
+
+  $.showOverlay = function (zIndex) {
+      var $overlay = $('.mdui-overlay');
+      if ($overlay.length) {
+          $overlay.data('_overlay_is_deleted', false);
+          if (!isUndefined(zIndex)) {
+              $overlay.css('z-index', zIndex);
+          }
+      }
+      else {
+          if (isUndefined(zIndex)) {
+              zIndex = 2000;
+          }
+          $overlay = $('<div class="mdui-overlay">')
+              .appendTo(document.body)
+              .reflow()
+              .css('z-index', zIndex);
+      }
+      var level = $overlay.data('_overlay_level') || 0;
+      return $overlay.data('_overlay_level', ++level).addClass('mdui-overlay-show');
+  };
+
+  $.hideOverlay = function (force) {
+      if ( force === void 0 ) force = false;
+
+      var $overlay = $('.mdui-overlay');
+      if (!$overlay.length) {
+          return;
+      }
+      var level = force ? 1 : $overlay.data('_overlay_level');
+      if (level > 1) {
+          $overlay.data('_overlay_level', --level);
+          return;
+      }
+      $overlay
+          .data('_overlay_level', 0)
+          .removeClass('mdui-overlay-show')
+          .data('_overlay_is_deleted', true)
+          .transitionEnd(function () {
+          if ($overlay.data('_overlay_is_deleted')) {
+              $overlay.remove();
+          }
+      });
+  };
+
+  $.lockScreen = function () {
+      var $body = $('body');
+      // 不直接把 body 设为 box-sizing: border-box,避免污染全局样式
+      var newBodyWidth = $body.width();
+      var level = $body.data('_lockscreen_level') || 0;
+      $body
+          .addClass('mdui-locked')
+          .width(newBodyWidth)
+          .data('_lockscreen_level', ++level);
+  };
+
+  $.unlockScreen = function (force) {
+      if ( force === void 0 ) force = false;
+
+      var $body = $('body');
+      var level = force ? 1 : $body.data('_lockscreen_level');
+      if (level > 1) {
+          $body.data('_lockscreen_level', --level);
+          return;
+      }
+      $body.data('_lockscreen_level', 0).removeClass('mdui-locked').width('');
+  };
+
+  $.throttle = function (fn, delay) {
+      if ( delay === void 0 ) delay = 16;
+
+      var timer = null;
+      return function () {
+          var this$1 = this;
+          var args = [], len = arguments.length;
+          while ( len-- ) args[ len ] = arguments[ len ];
+
+          if (isNull(timer)) {
+              timer = setTimeout(function () {
+                  fn.apply(this$1, args);
+                  timer = null;
+              }, delay);
+          }
+      };
+  };
+
+  var GUID = {};
+  $.guid = function (name) {
+      if (!isUndefined(name) && !isUndefined(GUID[name])) {
+          return GUID[name];
+      }
+      function s4() {
+          return Math.floor((1 + Math.random()) * 0x10000)
+              .toString(16)
+              .substring(1);
+      }
+      var guid = '_' +
+          s4() +
+          s4() +
+          '-' +
+          s4() +
+          '-' +
+          s4() +
+          '-' +
+          s4() +
+          '-' +
+          s4() +
+          s4() +
+          s4();
+      if (!isUndefined(name)) {
+          GUID[name] = guid;
+      }
+      return guid;
+  };
+
+  mdui.mutation = function (selector, apiInit) {
+      if (isUndefined(selector) || isUndefined(apiInit)) {
+          $(document).mutation();
+          return;
+      }
+      entries[selector] = apiInit;
+      $(selector).each(function (i, element) { return mutation(selector, apiInit, i, element); });
+  };
+
+  /**
+   * 触发组件上的事件
+   * @param eventName 事件名
+   * @param componentName 组件名
+   * @param target 在该元素上触发事件
+   * @param instance 组件实例
+   * @param parameters 事件参数
+   */
+  function componentEvent(eventName, componentName, target, instance, parameters) {
+      if (!parameters) {
+          parameters = {};
+      }
+      // @ts-ignore
+      parameters.inst = instance;
+      var fullEventName = eventName + ".mdui." + componentName;
+      // jQuery 事件
+      // @ts-ignore
+      if (typeof jQuery !== 'undefined') {
+          // @ts-ignore
+          jQuery(target).trigger(fullEventName, parameters);
+      }
+      var $target = $(target);
+      // mdui.jq 事件
+      $target.trigger(fullEventName, parameters);
+      var eventParams = {
+          bubbles: true,
+          cancelable: true,
+          detail: parameters,
+      };
+      var eventObject = new CustomEvent(fullEventName, eventParams);
+      // @ts-ignore
+      eventObject._detail = parameters;
+      $target[0].dispatchEvent(eventObject);
+  }
+
+  var $document = $(document);
+  var $window = $(window);
+  $('body');
+
+  var DEFAULT_OPTIONS = {
+      tolerance: 5,
+      offset: 0,
+      initialClass: 'mdui-headroom',
+      pinnedClass: 'mdui-headroom-pinned-top',
+      unpinnedClass: 'mdui-headroom-unpinned-top',
+  };
+  var Headroom = function Headroom(selector, options) {
+      if ( options === void 0 ) options = {};
+
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS);
+      /**
+       * 当前 headroom 的状态
+       */
+      this.state = 'pinned';
+      /**
+       * 当前是否启用
+       */
+      this.isEnable = false;
+      /**
+       * 上次滚动后,垂直方向的距离
+       */
+      this.lastScrollY = 0;
+      /**
+       * AnimationFrame ID
+       */
+      this.rafId = 0;
+      this.$element = $(selector).first();
+      extend(this.options, options);
+      // tolerance 参数若为数值,转换为对象
+      var tolerance = this.options.tolerance;
+      if (isNumber(tolerance)) {
+          this.options.tolerance = {
+              down: tolerance,
+              up: tolerance,
+          };
+      }
+      this.enable();
+  };
+  /**
+   * 滚动时的处理
+   */
+  Headroom.prototype.onScroll = function onScroll () {
+          var this$1 = this;
+
+      this.rafId = window.requestAnimationFrame(function () {
+          var currentScrollY = window.pageYOffset;
+          var direction = currentScrollY > this$1.lastScrollY ? 'down' : 'up';
+          var tolerance = this$1.options.tolerance[direction];
+          var scrolled = Math.abs(currentScrollY - this$1.lastScrollY);
+          var toleranceExceeded = scrolled >= tolerance;
+          if (currentScrollY > this$1.lastScrollY &&
+              currentScrollY >= this$1.options.offset &&
+              toleranceExceeded) {
+              this$1.unpin();
+          }
+          else if ((currentScrollY < this$1.lastScrollY && toleranceExceeded) ||
+              currentScrollY <= this$1.options.offset) {
+              this$1.pin();
+          }
+          this$1.lastScrollY = currentScrollY;
+      });
+  };
+  /**
+   * 触发组件事件
+   * @param name
+   */
+  Headroom.prototype.triggerEvent = function triggerEvent (name) {
+      componentEvent(name, 'headroom', this.$element, this);
+  };
+  /**
+   * 动画结束的回调
+   */
+  Headroom.prototype.transitionEnd = function transitionEnd () {
+      if (this.state === 'pinning') {
+          this.state = 'pinned';
+          this.triggerEvent('pinned');
+      }
+      if (this.state === 'unpinning') {
+          this.state = 'unpinned';
+          this.triggerEvent('unpinned');
+      }
+  };
+  /**
+   * 使元素固定住
+   */
+  Headroom.prototype.pin = function pin () {
+          var this$1 = this;
+
+      if (this.state === 'pinning' ||
+          this.state === 'pinned' ||
+          !this.$element.hasClass(this.options.initialClass)) {
+          return;
+      }
+      this.triggerEvent('pin');
+      this.state = 'pinning';
+      this.$element
+          .removeClass(this.options.unpinnedClass)
+          .addClass(this.options.pinnedClass)
+          .transitionEnd(function () { return this$1.transitionEnd(); });
+  };
+  /**
+   * 使元素隐藏
+   */
+  Headroom.prototype.unpin = function unpin () {
+          var this$1 = this;
+
+      if (this.state === 'unpinning' ||
+          this.state === 'unpinned' ||
+          !this.$element.hasClass(this.options.initialClass)) {
+          return;
+      }
+      this.triggerEvent('unpin');
+      this.state = 'unpinning';
+      this.$element
+          .removeClass(this.options.pinnedClass)
+          .addClass(this.options.unpinnedClass)
+          .transitionEnd(function () { return this$1.transitionEnd(); });
+  };
+  /**
+   * 启用 headroom 插件
+   */
+  Headroom.prototype.enable = function enable () {
+          var this$1 = this;
+
+      if (this.isEnable) {
+          return;
+      }
+      this.isEnable = true;
+      this.state = 'pinned';
+      this.$element
+          .addClass(this.options.initialClass)
+          .removeClass(this.options.pinnedClass)
+          .removeClass(this.options.unpinnedClass);
+      this.lastScrollY = window.pageYOffset;
+      $window.on('scroll', function () { return this$1.onScroll(); });
+  };
+  /**
+   * 禁用 headroom 插件
+   */
+  Headroom.prototype.disable = function disable () {
+          var this$1 = this;
+
+      if (!this.isEnable) {
+          return;
+      }
+      this.isEnable = false;
+      this.$element
+          .removeClass(this.options.initialClass)
+          .removeClass(this.options.pinnedClass)
+          .removeClass(this.options.unpinnedClass);
+      $window.off('scroll', function () { return this$1.onScroll(); });
+      window.cancelAnimationFrame(this.rafId);
+  };
+  /**
+   * 获取当前状态。共包含四种状态:`pinning`、`pinned`、`unpinning`、`unpinned`
+   */
+  Headroom.prototype.getState = function getState () {
+      return this.state;
+  };
+  mdui.Headroom = Headroom;
+
+  /**
+   * 解析 DATA API 参数
+   * @param element 元素
+   * @param name 属性名
+   */
+  function parseOptions(element, name) {
+      var attr = $(element).attr(name);
+      if (!attr) {
+          return {};
+      }
+      return new Function('', ("var json = " + attr + "; return JSON.parse(JSON.stringify(json));"))();
+  }
+
+  var customAttr = 'mdui-headroom';
+  $(function () {
+      mdui.mutation(("[" + customAttr + "]"), function () {
+          new mdui.Headroom(this, parseOptions(this, customAttr));
+      });
+  });
+
+  var DEFAULT_OPTIONS$1 = {
+      accordion: false,
+  };
+  var CollapseAbstract = function CollapseAbstract(selector, options) {
+      if ( options === void 0 ) options = {};
+
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS$1);
+      // CSS 类名
+      var classPrefix = "mdui-" + (this.getNamespace()) + "-item";
+      this.classItem = classPrefix;
+      this.classItemOpen = classPrefix + "-open";
+      this.classHeader = classPrefix + "-header";
+      this.classBody = classPrefix + "-body";
+      this.$element = $(selector).first();
+      extend(this.options, options);
+      this.bindEvent();
+  };
+  /**
+   * 绑定事件
+   */
+  CollapseAbstract.prototype.bindEvent = function bindEvent () {
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      var that = this;
+      // 点击 header 时,打开/关闭 item
+      this.$element.on('click', ("." + (this.classHeader)), function () {
+          var $header = $(this);
+          var $item = $header.parent();
+          var $items = that.getItems();
+          $items.each(function (_, item) {
+              if ($item.is(item)) {
+                  that.toggle(item);
+              }
+          });
+      });
+      // 点击关闭按钮时,关闭 item
+      this.$element.on('click', ("[mdui-" + (this.getNamespace()) + "-item-close]"), function () {
+          var $target = $(this);
+          var $item = $target.parents(("." + (that.classItem))).first();
+          that.close($item);
+      });
+  };
+  /**
+   * 指定 item 是否处于打开状态
+   * @param $item
+   */
+  CollapseAbstract.prototype.isOpen = function isOpen ($item) {
+      return $item.hasClass(this.classItemOpen);
+  };
+  /**
+   * 获取所有 item
+   */
+  CollapseAbstract.prototype.getItems = function getItems () {
+      return this.$element.children(("." + (this.classItem)));
+  };
+  /**
+   * 获取指定 item
+   * @param item
+   */
+  CollapseAbstract.prototype.getItem = function getItem (item) {
+      if (isNumber(item)) {
+          return this.getItems().eq(item);
+      }
+      return $(item).first();
+  };
+  /**
+   * 触发组件事件
+   * @param name 事件名
+   * @param $item 事件触发的目标 item
+   */
+  CollapseAbstract.prototype.triggerEvent = function triggerEvent (name, $item) {
+      componentEvent(name, this.getNamespace(), $item, this);
+  };
+  /**
+   * 动画结束回调
+   * @param $content body 元素
+   * @param $item item 元素
+   */
+  CollapseAbstract.prototype.transitionEnd = function transitionEnd ($content, $item) {
+      if (this.isOpen($item)) {
+          $content.transition(0).height('auto').reflow().transition('');
+          this.triggerEvent('opened', $item);
+      }
+      else {
+          $content.height('');
+          this.triggerEvent('closed', $item);
+      }
+  };
+  /**
+   * 打开指定面板项
+   * @param item 面板项的索引号、或 CSS 选择器、或 DOM 元素、或 JQ 对象
+   */
+  CollapseAbstract.prototype.open = function open (item) {
+          var this$1 = this;
+
+      var $item = this.getItem(item);
+      if (this.isOpen($item)) {
+          return;
+      }
+      // 关闭其他项
+      if (this.options.accordion) {
+          this.$element.children(("." + (this.classItemOpen))).each(function (_, element) {
+              var $element = $(element);
+              if (!$element.is($item)) {
+                  this$1.close($element);
+              }
+          });
+      }
+      var $content = $item.children(("." + (this.classBody)));
+      $content
+          .height($content[0].scrollHeight)
+          .transitionEnd(function () { return this$1.transitionEnd($content, $item); });
+      this.triggerEvent('open', $item);
+      $item.addClass(this.classItemOpen);
+  };
+  /**
+   * 关闭指定面板项
+   * @param item 面板项的索引号、或 CSS 选择器、或 DOM 元素、或 JQ 对象
+   */
+  CollapseAbstract.prototype.close = function close (item) {
+          var this$1 = this;
+
+      var $item = this.getItem(item);
+      if (!this.isOpen($item)) {
+          return;
+      }
+      var $content = $item.children(("." + (this.classBody)));
+      this.triggerEvent('close', $item);
+      $item.removeClass(this.classItemOpen);
+      $content
+          .transition(0)
+          .height($content[0].scrollHeight)
+          .reflow()
+          .transition('')
+          .height('')
+          .transitionEnd(function () { return this$1.transitionEnd($content, $item); });
+  };
+  /**
+   * 切换指定面板项的打开状态
+   * @param item 面板项的索引号、或 CSS 选择器、或 DOM 元素、或 JQ 对象
+   */
+  CollapseAbstract.prototype.toggle = function toggle (item) {
+      var $item = this.getItem(item);
+      this.isOpen($item) ? this.close($item) : this.open($item);
+  };
+  /**
+   * 打开所有面板项
+   */
+  CollapseAbstract.prototype.openAll = function openAll () {
+          var this$1 = this;
+
+      this.getItems().each(function (_, element) { return this$1.open(element); });
+  };
+  /**
+   * 关闭所有面板项
+   */
+  CollapseAbstract.prototype.closeAll = function closeAll () {
+          var this$1 = this;
+
+      this.getItems().each(function (_, element) { return this$1.close(element); });
+  };
+
+  var Collapse = /*@__PURE__*/(function (CollapseAbstract) {
+      function Collapse () {
+          CollapseAbstract.apply(this, arguments);
+      }
+
+      if ( CollapseAbstract ) Collapse.__proto__ = CollapseAbstract;
+      Collapse.prototype = Object.create( CollapseAbstract && CollapseAbstract.prototype );
+      Collapse.prototype.constructor = Collapse;
+
+      Collapse.prototype.getNamespace = function getNamespace () {
+          return 'collapse';
+      };
+
+      return Collapse;
+  }(CollapseAbstract));
+  mdui.Collapse = Collapse;
+
+  var customAttr$1 = 'mdui-collapse';
+  $(function () {
+      mdui.mutation(("[" + customAttr$1 + "]"), function () {
+          new mdui.Collapse(this, parseOptions(this, customAttr$1));
+      });
+  });
+
+  var Panel = /*@__PURE__*/(function (CollapseAbstract) {
+      function Panel () {
+          CollapseAbstract.apply(this, arguments);
+      }
+
+      if ( CollapseAbstract ) Panel.__proto__ = CollapseAbstract;
+      Panel.prototype = Object.create( CollapseAbstract && CollapseAbstract.prototype );
+      Panel.prototype.constructor = Panel;
+
+      Panel.prototype.getNamespace = function getNamespace () {
+          return 'panel';
+      };
+
+      return Panel;
+  }(CollapseAbstract));
+  mdui.Panel = Panel;
+
+  var customAttr$2 = 'mdui-panel';
+  $(function () {
+      mdui.mutation(("[" + customAttr$2 + "]"), function () {
+          new mdui.Panel(this, parseOptions(this, customAttr$2));
+      });
+  });
+
+  var Table = function Table(selector) {
+      /**
+       * 表头 tr 元素
+       */
+      this.$thRow = $();
+      /**
+       * 表格 body 中的 tr 元素
+       */
+      this.$tdRows = $();
+      /**
+       * 表头的 checkbox 元素
+       */
+      this.$thCheckbox = $();
+      /**
+       * 表格 body 中的 checkbox 元素
+       */
+      this.$tdCheckboxs = $();
+      /**
+       * 表格行是否可选择
+       */
+      this.selectable = false;
+      /**
+       * 已选中的行数
+       */
+      this.selectedRow = 0;
+      this.$element = $(selector).first();
+      this.init();
+  };
+  /**
+   * 初始化表格
+   */
+  Table.prototype.init = function init () {
+      this.$thRow = this.$element.find('thead tr');
+      this.$tdRows = this.$element.find('tbody tr');
+      this.selectable = this.$element.hasClass('mdui-table-selectable');
+      this.updateThCheckbox();
+      this.updateTdCheckbox();
+      this.updateNumericCol();
+  };
+  /**
+   * 生成 checkbox 的 HTML 结构
+   * @param tag 标签名
+   */
+  Table.prototype.createCheckboxHTML = function createCheckboxHTML (tag) {
+      return ("<" + tag + " class=\"mdui-table-cell-checkbox\">" +
+          '<label class="mdui-checkbox">' +
+          '<input type="checkbox"/>' +
+          '<i class="mdui-checkbox-icon"></i>' +
+          '</label>' +
+          "</" + tag + ">");
+  };
+  /**
+   * 更新表头 checkbox 的状态
+   */
+  Table.prototype.updateThCheckboxStatus = function updateThCheckboxStatus () {
+      var checkbox = this.$thCheckbox[0];
+      var selectedRow = this.selectedRow;
+      var tdRowsLength = this.$tdRows.length;
+      checkbox.checked = selectedRow === tdRowsLength;
+      checkbox.indeterminate = !!selectedRow && selectedRow !== tdRowsLength;
+  };
+  /**
+   * 更新表格行的 checkbox
+   */
+  Table.prototype.updateTdCheckbox = function updateTdCheckbox () {
+          var this$1 = this;
+
+      var rowSelectedClass = 'mdui-table-row-selected';
+      this.$tdRows.each(function (_, row) {
+          var $row = $(row);
+          // 移除旧的 checkbox
+          $row.find('.mdui-table-cell-checkbox').remove();
+          if (!this$1.selectable) {
+              return;
+          }
+          // 创建 DOM
+          var $checkbox = $(this$1.createCheckboxHTML('td'))
+              .prependTo($row)
+              .find('input[type="checkbox"]');
+          // 默认选中的行
+          if ($row.hasClass(rowSelectedClass)) {
+              $checkbox[0].checked = true;
+              this$1.selectedRow++;
+          }
+          this$1.updateThCheckboxStatus();
+          // 绑定事件
+          $checkbox.on('change', function () {
+              if ($checkbox[0].checked) {
+                  $row.addClass(rowSelectedClass);
+                  this$1.selectedRow++;
+              }
+              else {
+                  $row.removeClass(rowSelectedClass);
+                  this$1.selectedRow--;
+              }
+              this$1.updateThCheckboxStatus();
+          });
+          this$1.$tdCheckboxs = this$1.$tdCheckboxs.add($checkbox);
+      });
+  };
+  /**
+   * 更新表头的 checkbox
+   */
+  Table.prototype.updateThCheckbox = function updateThCheckbox () {
+          var this$1 = this;
+
+      // 移除旧的 checkbox
+      this.$thRow.find('.mdui-table-cell-checkbox').remove();
+      if (!this.selectable) {
+          return;
+      }
+      this.$thCheckbox = $(this.createCheckboxHTML('th'))
+          .prependTo(this.$thRow)
+          .find('input[type="checkbox"]')
+          .on('change', function () {
+          var isCheckedAll = this$1.$thCheckbox[0].checked;
+          this$1.selectedRow = isCheckedAll ? this$1.$tdRows.length : 0;
+          this$1.$tdCheckboxs.each(function (_, checkbox) {
+              checkbox.checked = isCheckedAll;
+          });
+          this$1.$tdRows.each(function (_, row) {
+              isCheckedAll
+                  ? $(row).addClass('mdui-table-row-selected')
+                  : $(row).removeClass('mdui-table-row-selected');
+          });
+      });
+  };
+  /**
+   * 更新数值列
+   */
+  Table.prototype.updateNumericCol = function updateNumericCol () {
+          var this$1 = this;
+
+      var numericClass = 'mdui-table-col-numeric';
+      this.$thRow.find('th').each(function (i, th) {
+          var isNumericCol = $(th).hasClass(numericClass);
+          this$1.$tdRows.each(function (_, row) {
+              var $td = $(row).find('td').eq(i);
+              isNumericCol
+                  ? $td.addClass(numericClass)
+                  : $td.removeClass(numericClass);
+          });
+      });
+  };
+  var dataName = '_mdui_table';
+  $(function () {
+      mdui.mutation('.mdui-table', function () {
+          var $element = $(this);
+          if (!$element.data(dataName)) {
+              $element.data(dataName, new Table($element));
+          }
+      });
+  });
+  mdui.updateTables = function (selector) {
+      var $elements = isUndefined(selector) ? $('.mdui-table') : $(selector);
+      $elements.each(function (_, element) {
+          var $element = $(element);
+          var instance = $element.data(dataName);
+          if (instance) {
+              instance.init();
+          }
+          else {
+              $element.data(dataName, new Table($element));
+          }
+      });
+  };
+
+  /**
+   * touch 事件后的 500ms 内禁用 mousedown 事件
+   *
+   * 不支持触控的屏幕上事件顺序为 mousedown -> mouseup -> click
+   * 支持触控的屏幕上事件顺序为 touchstart -> touchend -> mousedown -> mouseup -> click
+   *
+   * 在每一个事件中都使用 TouchHandler.isAllow(event) 判断事件是否可执行
+   * 在 touchstart 和 touchmove、touchend、touchcancel
+   *
+   * (function () {
+   *   $document
+   *     .on(start, function (e) {
+   *       if (!isAllow(e)) {
+   *         return;
+   *       }
+   *       register(e);
+   *       console.log(e.type);
+   *     })
+   *     .on(move, function (e) {
+   *       if (!isAllow(e)) {
+   *         return;
+   *       }
+   *       console.log(e.type);
+   *     })
+   *     .on(end, function (e) {
+   *       if (!isAllow(e)) {
+   *         return;
+   *       }
+   *       console.log(e.type);
+   *     })
+   *     .on(unlock, register);
+   * })();
+   */
+  var startEvent = 'touchstart mousedown';
+  var moveEvent = 'touchmove mousemove';
+  var endEvent = 'touchend mouseup';
+  var cancelEvent = 'touchcancel mouseleave';
+  var unlockEvent = 'touchend touchmove touchcancel';
+  var touches = 0;
+  /**
+   * 该事件是否被允许,在执行事件前调用该方法判断事件是否可以执行
+   * 若已触发 touch 事件,则阻止之后的鼠标事件
+   * @param event
+   */
+  function isAllow(event) {
+      return !(touches &&
+          [
+              'mousedown',
+              'mouseup',
+              'mousemove',
+              'click',
+              'mouseover',
+              'mouseout',
+              'mouseenter',
+              'mouseleave' ].indexOf(event.type) > -1);
+  }
+  /**
+   * 在 touchstart 和 touchmove、touchend、touchcancel 事件中调用该方法注册事件
+   * @param event
+   */
+  function register(event) {
+      if (event.type === 'touchstart') {
+          // 触发了 touch 事件
+          touches += 1;
+      }
+      else if (['touchmove', 'touchend', 'touchcancel'].indexOf(event.type) > -1) {
+          // touch 事件结束 500ms 后解除对鼠标事件的阻止
+          setTimeout(function () {
+              if (touches) {
+                  touches -= 1;
+              }
+          }, 500);
+      }
+  }
+
+  /**
+   * Inspired by https://github.com/nolimits4web/Framework7/blob/master/src/js/fast-clicks.js
+   * https://github.com/nolimits4web/Framework7/blob/master/LICENSE
+   *
+   * Inspired by https://github.com/fians/Waves
+   */
+  /**
+   * 显示涟漪动画
+   * @param event
+   * @param $ripple
+   */
+  function show(event, $ripple) {
+      // 鼠标右键不产生涟漪
+      if (event instanceof MouseEvent && event.button === 2) {
+          return;
+      }
+      // 点击位置坐标
+      var touchPosition = typeof TouchEvent !== 'undefined' &&
+          event instanceof TouchEvent &&
+          event.touches.length
+          ? event.touches[0]
+          : event;
+      var touchStartX = touchPosition.pageX;
+      var touchStartY = touchPosition.pageY;
+      // 涟漪位置
+      var offset = $ripple.offset();
+      var height = $ripple.innerHeight();
+      var width = $ripple.innerWidth();
+      var center = {
+          x: touchStartX - offset.left,
+          y: touchStartY - offset.top,
+      };
+      var diameter = Math.max(Math.pow(Math.pow(height, 2) + Math.pow(width, 2), 0.5), 48);
+      // 涟漪扩散动画
+      var translate = "translate3d(" + (-center.x + width / 2) + "px," +
+          (-center.y + height / 2) + "px, 0) scale(1)";
+      // 涟漪的 DOM 结构,并缓存动画效果
+      $("<div class=\"mdui-ripple-wave\" " +
+          "style=\"width:" + diameter + "px;height:" + diameter + "px;" +
+          "margin-top:-" + (diameter / 2) + "px;margin-left:-" + (diameter / 2) + "px;" +
+          "left:" + (center.x) + "px;top:" + (center.y) + "px;\"></div>")
+          .data('_ripple_wave_translate', translate)
+          .prependTo($ripple)
+          .reflow()
+          .transform(translate);
+  }
+  /**
+   * 隐藏并移除涟漪
+   * @param $wave
+   */
+  function removeRipple($wave) {
+      if (!$wave.length || $wave.data('_ripple_wave_removed')) {
+          return;
+      }
+      $wave.data('_ripple_wave_removed', true);
+      var removeTimer = setTimeout(function () { return $wave.remove(); }, 400);
+      var translate = $wave.data('_ripple_wave_translate');
+      $wave
+          .addClass('mdui-ripple-wave-fill')
+          .transform(translate.replace('scale(1)', 'scale(1.01)'))
+          .transitionEnd(function () {
+          clearTimeout(removeTimer);
+          $wave
+              .addClass('mdui-ripple-wave-out')
+              .transform(translate.replace('scale(1)', 'scale(1.01)'));
+          removeTimer = setTimeout(function () { return $wave.remove(); }, 700);
+          setTimeout(function () {
+              $wave.transitionEnd(function () {
+                  clearTimeout(removeTimer);
+                  $wave.remove();
+              });
+          }, 0);
+      });
+  }
+  /**
+   * 隐藏涟漪动画
+   * @param this
+   */
+  function hide() {
+      var $ripple = $(this);
+      $ripple.children('.mdui-ripple-wave').each(function (_, wave) {
+          removeRipple($(wave));
+      });
+      $ripple.off((moveEvent + " " + endEvent + " " + cancelEvent), hide);
+  }
+  /**
+   * 显示涟漪,并绑定 touchend 等事件
+   * @param event
+   */
+  function showRipple(event) {
+      if (!isAllow(event)) {
+          return;
+      }
+      register(event);
+      // Chrome 59 点击滚动条时,会在 document 上触发事件
+      if (event.target === document) {
+          return;
+      }
+      var $target = $(event.target);
+      // 获取含 .mdui-ripple 类的元素
+      var $ripple = $target.hasClass('mdui-ripple')
+          ? $target
+          : $target.parents('.mdui-ripple').first();
+      if (!$ripple.length) {
+          return;
+      }
+      // 禁用状态的元素上不产生涟漪效果
+      if ($ripple.prop('disabled') || !isUndefined($ripple.attr('disabled'))) {
+          return;
+      }
+      if (event.type === 'touchstart') {
+          var hidden = false;
+          // touchstart 触发指定时间后开始涟漪动画,避免手指滑动时也触发涟漪
+          var timer = setTimeout(function () {
+              timer = 0;
+              show(event, $ripple);
+          }, 200);
+          var hideRipple = function () {
+              // 如果手指没有移动,且涟漪动画还没有开始,则开始涟漪动画
+              if (timer) {
+                  clearTimeout(timer);
+                  timer = 0;
+                  show(event, $ripple);
+              }
+              if (!hidden) {
+                  hidden = true;
+                  hide.call($ripple);
+              }
+          };
+          // 手指移动后,移除涟漪动画
+          var touchMove = function () {
+              if (timer) {
+                  clearTimeout(timer);
+                  timer = 0;
+              }
+              hideRipple();
+          };
+          $ripple.on('touchmove', touchMove).on('touchend touchcancel', hideRipple);
+      }
+      else {
+          show(event, $ripple);
+          $ripple.on((moveEvent + " " + endEvent + " " + cancelEvent), hide);
+      }
+  }
+  $(function () {
+      $document.on(startEvent, showRipple).on(unlockEvent, register);
+  });
+
+  var defaultData = {
+      reInit: false,
+      domLoadedEvent: false,
+  };
+  /**
+   * 输入框事件
+   * @param event
+   * @param data
+   */
+  function inputEvent(event, data) {
+      if ( data === void 0 ) data = {};
+
+      data = extend({}, defaultData, data);
+      var input = event.target;
+      var $input = $(input);
+      var eventType = event.type;
+      var value = $input.val();
+      // 文本框类型
+      var inputType = $input.attr('type') || '';
+      if (['checkbox', 'button', 'submit', 'range', 'radio', 'image'].indexOf(inputType) > -1) {
+          return;
+      }
+      var $textfield = $input.parent('.mdui-textfield');
+      // 输入框是否聚焦
+      if (eventType === 'focus') {
+          $textfield.addClass('mdui-textfield-focus');
+      }
+      if (eventType === 'blur') {
+          $textfield.removeClass('mdui-textfield-focus');
+      }
+      // 输入框是否为空
+      if (eventType === 'blur' || eventType === 'input') {
+          value
+              ? $textfield.addClass('mdui-textfield-not-empty')
+              : $textfield.removeClass('mdui-textfield-not-empty');
+      }
+      // 输入框是否禁用
+      input.disabled
+          ? $textfield.addClass('mdui-textfield-disabled')
+          : $textfield.removeClass('mdui-textfield-disabled');
+      // 表单验证
+      if ((eventType === 'input' || eventType === 'blur') &&
+          !data.domLoadedEvent &&
+          input.validity) {
+          input.validity.valid
+              ? $textfield.removeClass('mdui-textfield-invalid-html5')
+              : $textfield.addClass('mdui-textfield-invalid-html5');
+      }
+      // textarea 高度自动调整
+      if ($input.is('textarea')) {
+          // IE bug:textarea 的值仅为多个换行,不含其他内容时,textarea 的高度不准确
+          //         此时,在计算高度前,在值的开头加入一个空格,计算完后,移除空格
+          var inputValue = value;
+          var hasExtraSpace = false;
+          if (inputValue.replace(/[\r\n]/g, '') === '') {
+              $input.val(' ' + inputValue);
+              hasExtraSpace = true;
+          }
+          // 设置 textarea 高度
+          $input.outerHeight('');
+          var height = $input.outerHeight();
+          var scrollHeight = input.scrollHeight;
+          if (scrollHeight > height) {
+              $input.outerHeight(scrollHeight);
+          }
+          // 计算完,还原 textarea 的值
+          if (hasExtraSpace) {
+              $input.val(inputValue);
+          }
+      }
+      // 实时字数统计
+      if (data.reInit) {
+          $textfield.find('.mdui-textfield-counter').remove();
+      }
+      var maxLength = $input.attr('maxlength');
+      if (maxLength) {
+          if (data.reInit || data.domLoadedEvent) {
+              $('<div class="mdui-textfield-counter">' +
+                  "<span class=\"mdui-textfield-counter-inputed\"></span> / " + maxLength +
+                  '</div>').appendTo($textfield);
+          }
+          $textfield
+              .find('.mdui-textfield-counter-inputed')
+              .text(value.length.toString());
+      }
+      // 含 帮助文本、错误提示、字数统计 时,增加文本框底部内边距
+      if ($textfield.find('.mdui-textfield-helper').length ||
+          $textfield.find('.mdui-textfield-error').length ||
+          maxLength) {
+          $textfield.addClass('mdui-textfield-has-bottom');
+      }
+  }
+  $(function () {
+      // 绑定事件
+      $document.on('input focus blur', '.mdui-textfield-input', { useCapture: true }, inputEvent);
+      // 可展开文本框展开
+      $document.on('click', '.mdui-textfield-expandable .mdui-textfield-icon', function () {
+          $(this)
+              .parents('.mdui-textfield')
+              .addClass('mdui-textfield-expanded')
+              .find('.mdui-textfield-input')[0]
+              .focus();
+      });
+      // 可展开文本框关闭
+      $document.on('click', '.mdui-textfield-expanded .mdui-textfield-close', function () {
+          $(this)
+              .parents('.mdui-textfield')
+              .removeClass('mdui-textfield-expanded')
+              .find('.mdui-textfield-input')
+              .val('');
+      });
+      /**
+       * 初始化文本框
+       */
+      mdui.mutation('.mdui-textfield', function () {
+          $(this).find('.mdui-textfield-input').trigger('input', {
+              domLoadedEvent: true,
+          });
+      });
+  });
+  mdui.updateTextFields = function (selector) {
+      var $elements = isUndefined(selector) ? $('.mdui-textfield') : $(selector);
+      $elements.each(function (_, element) {
+          $(element).find('.mdui-textfield-input').trigger('input', {
+              reInit: true,
+          });
+      });
+  };
+
+  /**
+   * 滑块的值改变后修改滑块样式
+   * @param $slider
+   */
+  function updateValueStyle($slider) {
+      var data = $slider.data();
+      var $track = data._slider_$track;
+      var $fill = data._slider_$fill;
+      var $thumb = data._slider_$thumb;
+      var $input = data._slider_$input;
+      var min = data._slider_min;
+      var max = data._slider_max;
+      var isDisabled = data._slider_disabled;
+      var isDiscrete = data._slider_discrete;
+      var $thumbText = data._slider_$thumbText;
+      var value = $input.val();
+      var percent = ((value - min) / (max - min)) * 100;
+      $fill.width((percent + "%"));
+      $track.width(((100 - percent) + "%"));
+      if (isDisabled) {
+          $fill.css('padding-right', '6px');
+          $track.css('padding-left', '6px');
+      }
+      $thumb.css('left', (percent + "%"));
+      if (isDiscrete) {
+          $thumbText.text(value);
+      }
+      percent === 0
+          ? $slider.addClass('mdui-slider-zero')
+          : $slider.removeClass('mdui-slider-zero');
+  }
+  /**
+   * 重新初始化滑块
+   * @param $slider
+   */
+  function reInit($slider) {
+      var $track = $('<div class="mdui-slider-track"></div>');
+      var $fill = $('<div class="mdui-slider-fill"></div>');
+      var $thumb = $('<div class="mdui-slider-thumb"></div>');
+      var $input = $slider.find('input[type="range"]');
+      var isDisabled = $input[0].disabled;
+      var isDiscrete = $slider.hasClass('mdui-slider-discrete');
+      // 禁用状态
+      isDisabled
+          ? $slider.addClass('mdui-slider-disabled')
+          : $slider.removeClass('mdui-slider-disabled');
+      // 重新填充 HTML
+      $slider.find('.mdui-slider-track').remove();
+      $slider.find('.mdui-slider-fill').remove();
+      $slider.find('.mdui-slider-thumb').remove();
+      $slider.append($track).append($fill).append($thumb);
+      // 间续型滑块
+      var $thumbText = $();
+      if (isDiscrete) {
+          $thumbText = $('<span></span>');
+          $thumb.empty().append($thumbText);
+      }
+      $slider.data('_slider_$track', $track);
+      $slider.data('_slider_$fill', $fill);
+      $slider.data('_slider_$thumb', $thumb);
+      $slider.data('_slider_$input', $input);
+      $slider.data('_slider_min', $input.attr('min'));
+      $slider.data('_slider_max', $input.attr('max'));
+      $slider.data('_slider_disabled', isDisabled);
+      $slider.data('_slider_discrete', isDiscrete);
+      $slider.data('_slider_$thumbText', $thumbText);
+      // 设置默认值
+      updateValueStyle($slider);
+  }
+  var rangeSelector = '.mdui-slider input[type="range"]';
+  $(function () {
+      // 滑块滑动事件
+      $document.on('input change', rangeSelector, function () {
+          var $slider = $(this).parent();
+          updateValueStyle($slider);
+      });
+      // 开始触摸滑块事件
+      $document.on(startEvent, rangeSelector, function (event) {
+          if (!isAllow(event)) {
+              return;
+          }
+          register(event);
+          if (this.disabled) {
+              return;
+          }
+          var $slider = $(this).parent();
+          $slider.addClass('mdui-slider-focus');
+      });
+      // 结束触摸滑块事件
+      $document.on(endEvent, rangeSelector, function (event) {
+          if (!isAllow(event)) {
+              return;
+          }
+          if (this.disabled) {
+              return;
+          }
+          var $slider = $(this).parent();
+          $slider.removeClass('mdui-slider-focus');
+      });
+      $document.on(unlockEvent, rangeSelector, register);
+      /**
+       * 初始化滑块
+       */
+      mdui.mutation('.mdui-slider', function () {
+          reInit($(this));
+      });
+  });
+  mdui.updateSliders = function (selector) {
+      var $elements = isUndefined(selector) ? $('.mdui-slider') : $(selector);
+      $elements.each(function (_, element) {
+          reInit($(element));
+      });
+  };
+
+  var DEFAULT_OPTIONS$2 = {
+      trigger: 'hover',
+  };
+  var Fab = function Fab(selector, options) {
+      var this$1 = this;
+      if ( options === void 0 ) options = {};
+
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS$2);
+      /**
+       * 当前 fab 的状态
+       */
+      this.state = 'closed';
+      this.$element = $(selector).first();
+      extend(this.options, options);
+      this.$btn = this.$element.find('.mdui-fab');
+      this.$dial = this.$element.find('.mdui-fab-dial');
+      this.$dialBtns = this.$dial.find('.mdui-fab');
+      if (this.options.trigger === 'hover') {
+          this.$btn.on('touchstart mouseenter', function () { return this$1.open(); });
+          this.$element.on('mouseleave', function () { return this$1.close(); });
+      }
+      if (this.options.trigger === 'click') {
+          this.$btn.on(startEvent, function () { return this$1.open(); });
+      }
+      // 触摸屏幕其他地方关闭快速拨号
+      $document.on(startEvent, function (event) {
+          if ($(event.target).parents('.mdui-fab-wrapper').length) {
+              return;
+          }
+          this$1.close();
+      });
+  };
+  /**
+   * 触发组件事件
+   * @param name
+   */
+  Fab.prototype.triggerEvent = function triggerEvent (name) {
+      componentEvent(name, 'fab', this.$element, this);
+  };
+  /**
+   * 当前是否为打开状态
+   */
+  Fab.prototype.isOpen = function isOpen () {
+      return this.state === 'opening' || this.state === 'opened';
+  };
+  /**
+   * 打开快速拨号菜单
+   */
+  Fab.prototype.open = function open () {
+          var this$1 = this;
+
+      if (this.isOpen()) {
+          return;
+      }
+      // 为菜单中的按钮添加不同的 transition-delay
+      this.$dialBtns.each(function (index, btn) {
+          var delay = (15 * (this$1.$dialBtns.length - index)) + "ms";
+          btn.style.transitionDelay = delay;
+          btn.style.webkitTransitionDelay = delay;
+      });
+      this.$dial.css('height', 'auto').addClass('mdui-fab-dial-show');
+      // 如果按钮中存在 .mdui-fab-opened 的图标,则进行图标切换
+      if (this.$btn.find('.mdui-fab-opened').length) {
+          this.$btn.addClass('mdui-fab-opened');
+      }
+      this.state = 'opening';
+      this.triggerEvent('open');
+      // 打开顺序为从下到上逐个打开,最上面的打开后才表示动画完成
+      this.$dialBtns.first().transitionEnd(function () {
+          if (this$1.$btn.hasClass('mdui-fab-opened')) {
+              this$1.state = 'opened';
+              this$1.triggerEvent('opened');
+          }
+      });
+  };
+  /**
+   * 关闭快速拨号菜单
+   */
+  Fab.prototype.close = function close () {
+          var this$1 = this;
+
+      if (!this.isOpen()) {
+          return;
+      }
+      // 为菜单中的按钮添加不同的 transition-delay
+      this.$dialBtns.each(function (index, btn) {
+          var delay = (15 * index) + "ms";
+          btn.style.transitionDelay = delay;
+          btn.style.webkitTransitionDelay = delay;
+      });
+      this.$dial.removeClass('mdui-fab-dial-show');
+      this.$btn.removeClass('mdui-fab-opened');
+      this.state = 'closing';
+      this.triggerEvent('close');
+      // 从上往下依次关闭,最后一个关闭后才表示动画完成
+      this.$dialBtns.last().transitionEnd(function () {
+          if (this$1.$btn.hasClass('mdui-fab-opened')) {
+              return;
+          }
+          this$1.state = 'closed';
+          this$1.triggerEvent('closed');
+          this$1.$dial.css('height', 0);
+      });
+  };
+  /**
+   * 切换快速拨号菜单的打开状态
+   */
+  Fab.prototype.toggle = function toggle () {
+      this.isOpen() ? this.close() : this.open();
+  };
+  /**
+   * 以动画的形式显示整个浮动操作按钮
+   */
+  Fab.prototype.show = function show () {
+      this.$element.removeClass('mdui-fab-hide');
+  };
+  /**
+   * 以动画的形式隐藏整个浮动操作按钮
+   */
+  Fab.prototype.hide = function hide () {
+      this.$element.addClass('mdui-fab-hide');
+  };
+  /**
+   * 返回当前快速拨号菜单的打开状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+   */
+  Fab.prototype.getState = function getState () {
+      return this.state;
+  };
+  mdui.Fab = Fab;
+
+  var customAttr$3 = 'mdui-fab';
+  $(function () {
+      // mouseenter 不冒泡,无法进行事件委托,这里用 mouseover 代替。
+      // 不管是 click 、 mouseover 还是 touchstart ,都先初始化。
+      $document.on('touchstart mousedown mouseover', ("[" + customAttr$3 + "]"), function () {
+          new mdui.Fab(this, parseOptions(this, customAttr$3));
+      });
+  });
+
+  /**
+   * 最终生成的元素结构为:
+   *  <select class="mdui-select" mdui-select="{position: 'top'}" style="display: none;"> // $native
+   *    <option value="1">State 1</option>
+   *    <option value="2">State 2</option>
+   *    <option value="3" disabled="">State 3</option>
+   *  </select>
+   *  <div class="mdui-select mdui-select-position-top" style="" id="88dec0e4-d4a2-c6d0-0e7f-1ba4501e0553"> // $element
+   *    <span class="mdui-select-selected">State 1</span> // $selected
+   *    <div class="mdui-select-menu" style="transform-origin: center 100% 0px;"> // $menu
+   *      <div class="mdui-select-menu-item mdui-ripple" selected="">State 1</div> // $items
+   *      <div class="mdui-select-menu-item mdui-ripple">State 2</div>
+   *      <div class="mdui-select-menu-item mdui-ripple" disabled="">State 3</div>
+   *    </div>
+   *  </div>
+   */
+  var DEFAULT_OPTIONS$3 = {
+      position: 'auto',
+      gutter: 16,
+  };
+  var Select = function Select(selector, options) {
+      var this$1 = this;
+      if ( options === void 0 ) options = {};
+
+      /**
+       * 生成的 `<div class="mdui-select">` 元素的 JQ 对象
+       */
+      this.$element = $();
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS$3);
+      /**
+       * select 的 size 属性的值,根据该值设置 select 的高度
+       */
+      this.size = 0;
+      /**
+       * 占位元素,显示已选中菜单项的文本
+       */
+      this.$selected = $();
+      /**
+       * 菜单项的外层元素的 JQ 对象
+       */
+      this.$menu = $();
+      /**
+       * 菜单项数组的 JQ 对象
+       */
+      this.$items = $();
+      /**
+       * 当前选中的菜单项的索引号
+       */
+      this.selectedIndex = 0;
+      /**
+       * 当前选中菜单项的文本
+       */
+      this.selectedText = '';
+      /**
+       * 当前选中菜单项的值
+       */
+      this.selectedValue = '';
+      /**
+       * 当前 select 的状态
+       */
+      this.state = 'closed';
+      this.$native = $(selector).first();
+      this.$native.hide();
+      extend(this.options, options);
+      // 为当前 select 生成唯一 ID
+      this.uniqueID = $.guid();
+      // 生成 select
+      this.handleUpdate();
+      // 点击 select 外面区域关闭
+      $document.on('click touchstart', function (event) {
+          var $target = $(event.target);
+          if (this$1.isOpen() &&
+              !$target.is(this$1.$element) &&
+              !contains(this$1.$element[0], $target[0])) {
+              this$1.close();
+          }
+      });
+  };
+  /**
+   * 调整菜单位置
+   */
+  Select.prototype.readjustMenu = function readjustMenu () {
+      var windowHeight = $window.height();
+      // mdui-select 高度
+      var elementHeight = this.$element.height();
+      // 菜单项高度
+      var $itemFirst = this.$items.first();
+      var itemHeight = $itemFirst.height();
+      var itemMargin = parseInt($itemFirst.css('margin-top'));
+      // 菜单高度
+      var menuWidth = this.$element.innerWidth() + 0.01; // 必须比真实宽度多一点,不然会出现省略号
+      var menuHeight = itemHeight * this.size + itemMargin * 2;
+      // mdui-select 在窗口中的位置
+      var elementTop = this.$element[0].getBoundingClientRect().top;
+      var transformOriginY;
+      var menuMarginTop;
+      if (this.options.position === 'bottom') {
+          menuMarginTop = elementHeight;
+          transformOriginY = '0px';
+      }
+      else if (this.options.position === 'top') {
+          menuMarginTop = -menuHeight - 1;
+          transformOriginY = '100%';
+      }
+      else {
+          // 菜单高度不能超过窗口高度
+          var menuMaxHeight = windowHeight - this.options.gutter * 2;
+          if (menuHeight > menuMaxHeight) {
+              menuHeight = menuMaxHeight;
+          }
+          // 菜单的 margin-top
+          menuMarginTop = -(itemMargin +
+              this.selectedIndex * itemHeight +
+              (itemHeight - elementHeight) / 2);
+          var menuMaxMarginTop = -(itemMargin +
+              (this.size - 1) * itemHeight +
+              (itemHeight - elementHeight) / 2);
+          if (menuMarginTop < menuMaxMarginTop) {
+              menuMarginTop = menuMaxMarginTop;
+          }
+          // 菜单不能超出窗口
+          var menuTop = elementTop + menuMarginTop;
+          if (menuTop < this.options.gutter) {
+              // 不能超出窗口上方
+              menuMarginTop = -(elementTop - this.options.gutter);
+          }
+          else if (menuTop + menuHeight + this.options.gutter > windowHeight) {
+              // 不能超出窗口下方
+              menuMarginTop = -(elementTop +
+                  menuHeight +
+                  this.options.gutter -
+                  windowHeight);
+          }
+          // transform 的 Y 轴坐标
+          transformOriginY = (this.selectedIndex * itemHeight + itemHeight / 2 + itemMargin) + "px";
+      }
+      // 设置样式
+      this.$element.innerWidth(menuWidth);
+      this.$menu
+          .innerWidth(menuWidth)
+          .height(menuHeight)
+          .css({
+          'margin-top': menuMarginTop + 'px',
+          'transform-origin': 'center ' + transformOriginY + ' 0',
+      });
+  };
+  /**
+   * select 是否为打开状态
+   */
+  Select.prototype.isOpen = function isOpen () {
+      return this.state === 'opening' || this.state === 'opened';
+  };
+  /**
+   * 对原生 select 组件进行了修改后,需要调用该方法
+   */
+  Select.prototype.handleUpdate = function handleUpdate () {
+          var this$1 = this;
+
+      if (this.isOpen()) {
+          this.close();
+      }
+      this.selectedValue = this.$native.val();
+      var itemsData = [];
+      this.$items = $();
+      // 生成 HTML
+      this.$native.find('option').each(function (index, option) {
+          var text = option.textContent || '';
+          var value = option.value;
+          var disabled = option.disabled;
+          var selected = this$1.selectedValue === value;
+          itemsData.push({
+              value: value,
+              text: text,
+              disabled: disabled,
+              selected: selected,
+              index: index,
+          });
+          if (selected) {
+              this$1.selectedText = text;
+              this$1.selectedIndex = index;
+          }
+          this$1.$items = this$1.$items.add('<div class="mdui-select-menu-item mdui-ripple"' +
+              (disabled ? ' disabled' : '') +
+              (selected ? ' selected' : '') +
+              ">" + text + "</div>");
+      });
+      this.$selected = $(("<span class=\"mdui-select-selected\">" + (this.selectedText) + "</span>"));
+      this.$element = $("<div class=\"mdui-select mdui-select-position-" + (this.options.position) + "\" " +
+          "style=\"" + (this.$native.attr('style')) + "\" " +
+          "id=\"" + (this.uniqueID) + "\"></div>")
+          .show()
+          .append(this.$selected);
+      this.$menu = $('<div class="mdui-select-menu"></div>')
+          .appendTo(this.$element)
+          .append(this.$items);
+      $(("#" + (this.uniqueID))).remove();
+      this.$native.after(this.$element);
+      // 根据 select 的 size 属性设置高度
+      this.size = parseInt(this.$native.attr('size') || '0');
+      if (this.size <= 0) {
+          this.size = this.$items.length;
+          if (this.size > 8) {
+              this.size = 8;
+          }
+      }
+      // 点击选项时关闭下拉菜单
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      var that = this;
+      this.$items.on('click', function () {
+          if (that.state === 'closing') {
+              return;
+          }
+          var $item = $(this);
+          var index = $item.index();
+          var data = itemsData[index];
+          if (data.disabled) {
+              return;
+          }
+          that.$selected.text(data.text);
+          that.$native.val(data.value);
+          that.$items.removeAttr('selected');
+          $item.attr('selected', '');
+          that.selectedIndex = data.index;
+          that.selectedValue = data.value;
+          that.selectedText = data.text;
+          that.$native.trigger('change');
+          that.close();
+      });
+      // 点击 $element 时打开下拉菜单
+      this.$element.on('click', function (event) {
+          var $target = $(event.target);
+          // 在菜单上点击时不打开
+          if ($target.is('.mdui-select-menu') ||
+              $target.is('.mdui-select-menu-item')) {
+              return;
+          }
+          this$1.toggle();
+      });
+  };
+  /**
+   * 动画结束的回调
+   */
+  Select.prototype.transitionEnd = function transitionEnd () {
+      this.$element.removeClass('mdui-select-closing');
+      if (this.state === 'opening') {
+          this.state = 'opened';
+          this.triggerEvent('opened');
+          this.$menu.css('overflow-y', 'auto');
+      }
+      if (this.state === 'closing') {
+          this.state = 'closed';
+          this.triggerEvent('closed');
+          // 恢复样式
+          this.$element.innerWidth('');
+          this.$menu.css({
+              'margin-top': '',
+              height: '',
+              width: '',
+          });
+      }
+  };
+  /**
+   * 触发组件事件
+   * @param name
+   */
+  Select.prototype.triggerEvent = function triggerEvent (name) {
+      componentEvent(name, 'select', this.$native, this);
+  };
+  /**
+   * 切换下拉菜单的打开状态
+   */
+  Select.prototype.toggle = function toggle () {
+      this.isOpen() ? this.close() : this.open();
+  };
+  /**
+   * 打开下拉菜单
+   */
+  Select.prototype.open = function open () {
+          var this$1 = this;
+
+      if (this.isOpen()) {
+          return;
+      }
+      this.state = 'opening';
+      this.triggerEvent('open');
+      this.readjustMenu();
+      this.$element.addClass('mdui-select-open');
+      this.$menu.transitionEnd(function () { return this$1.transitionEnd(); });
+  };
+  /**
+   * 关闭下拉菜单
+   */
+  Select.prototype.close = function close () {
+          var this$1 = this;
+
+      if (!this.isOpen()) {
+          return;
+      }
+      this.state = 'closing';
+      this.triggerEvent('close');
+      this.$menu.css('overflow-y', '');
+      this.$element
+          .removeClass('mdui-select-open')
+          .addClass('mdui-select-closing');
+      this.$menu.transitionEnd(function () { return this$1.transitionEnd(); });
+  };
+  /**
+   * 获取当前菜单的状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+   */
+  Select.prototype.getState = function getState () {
+      return this.state;
+  };
+  mdui.Select = Select;
+
+  var customAttr$4 = 'mdui-select';
+  $(function () {
+      mdui.mutation(("[" + customAttr$4 + "]"), function () {
+          new mdui.Select(this, parseOptions(this, customAttr$4));
+      });
+  });
+
+  $(function () {
+      // 滚动时隐藏应用栏
+      mdui.mutation('.mdui-appbar-scroll-hide', function () {
+          new mdui.Headroom(this);
+      });
+      // 滚动时只隐藏应用栏中的工具栏
+      mdui.mutation('.mdui-appbar-scroll-toolbar-hide', function () {
+          new mdui.Headroom(this, {
+              pinnedClass: 'mdui-headroom-pinned-toolbar',
+              unpinnedClass: 'mdui-headroom-unpinned-toolbar',
+          });
+      });
+  });
+
+  var DEFAULT_OPTIONS$4 = {
+      trigger: 'click',
+      loop: false,
+  };
+  var Tab = function Tab(selector, options) {
+      var this$1 = this;
+      if ( options === void 0 ) options = {};
+
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS$4);
+      /**
+       * 当前激活的 tab 的索引号。为 -1 时表示没有激活的选项卡,或不存在选项卡
+       */
+      this.activeIndex = -1;
+      this.$element = $(selector).first();
+      extend(this.options, options);
+      this.$tabs = this.$element.children('a');
+      this.$indicator = $('<div class="mdui-tab-indicator"></div>').appendTo(this.$element);
+      // 根据 url hash 获取默认激活的选项卡
+      var hash = window.location.hash;
+      if (hash) {
+          this.$tabs.each(function (index, tab) {
+              if ($(tab).attr('href') === hash) {
+                  this$1.activeIndex = index;
+                  return false;
+              }
+              return true;
+          });
+      }
+      // 含 .mdui-tab-active 的元素默认激活
+      if (this.activeIndex === -1) {
+          this.$tabs.each(function (index, tab) {
+              if ($(tab).hasClass('mdui-tab-active')) {
+                  this$1.activeIndex = index;
+                  return false;
+              }
+              return true;
+          });
+      }
+      // 存在选项卡时,默认激活第一个选项卡
+      if (this.$tabs.length && this.activeIndex === -1) {
+          this.activeIndex = 0;
+      }
+      // 设置激活状态选项卡
+      this.setActive();
+      // 监听窗口大小变化事件,调整指示器位置
+      $window.on('resize', $.throttle(function () { return this$1.setIndicatorPosition(); }, 100));
+      // 监听点击选项卡事件
+      this.$tabs.each(function (_, tab) {
+          this$1.bindTabEvent(tab);
+      });
+  };
+  /**
+   * 指定选项卡是否已禁用
+   * @param $tab
+   */
+  Tab.prototype.isDisabled = function isDisabled ($tab) {
+      return $tab.attr('disabled') !== undefined;
+  };
+  /**
+   * 绑定在 Tab 上点击或悬浮的事件
+   * @param tab
+   */
+  Tab.prototype.bindTabEvent = function bindTabEvent (tab) {
+          var this$1 = this;
+
+      var $tab = $(tab);
+      // 点击或鼠标移入触发的事件
+      var clickEvent = function () {
+          // 禁用状态的选项卡无法选中
+          if (this$1.isDisabled($tab)) {
+              return false;
+          }
+          this$1.activeIndex = this$1.$tabs.index(tab);
+          this$1.setActive();
+      };
+      // 无论 trigger 是 click 还是 hover,都会响应 click 事件
+      $tab.on('click', clickEvent);
+      // trigger 为 hover 时,额外响应 mouseenter 事件
+      if (this.options.trigger === 'hover') {
+          $tab.on('mouseenter', clickEvent);
+      }
+      // 阻止链接的默认点击动作
+      $tab.on('click', function () {
+          if (($tab.attr('href') || '').indexOf('#') === 0) {
+              return false;
+          }
+      });
+  };
+  /**
+   * 触发组件事件
+   * @param name
+   * @param $element
+   * @param parameters
+   */
+  Tab.prototype.triggerEvent = function triggerEvent (name, $element, parameters) {
+          if ( parameters === void 0 ) parameters = {};
+
+      componentEvent(name, 'tab', $element, this, parameters);
+  };
+  /**
+   * 设置激活状态的选项卡
+   */
+  Tab.prototype.setActive = function setActive () {
+          var this$1 = this;
+
+      this.$tabs.each(function (index, tab) {
+          var $tab = $(tab);
+          var targetId = $tab.attr('href') || '';
+          // 设置选项卡激活状态
+          if (index === this$1.activeIndex && !this$1.isDisabled($tab)) {
+              if (!$tab.hasClass('mdui-tab-active')) {
+                  this$1.triggerEvent('change', this$1.$element, {
+                      index: this$1.activeIndex,
+                      id: targetId.substr(1),
+                  });
+                  this$1.triggerEvent('show', $tab);
+                  $tab.addClass('mdui-tab-active');
+              }
+              $(targetId).show();
+              this$1.setIndicatorPosition();
+          }
+          else {
+              $tab.removeClass('mdui-tab-active');
+              $(targetId).hide();
+          }
+      });
+  };
+  /**
+   * 设置选项卡指示器的位置
+   */
+  Tab.prototype.setIndicatorPosition = function setIndicatorPosition () {
+      // 选项卡数量为 0 时,不显示指示器
+      if (this.activeIndex === -1) {
+          this.$indicator.css({
+              left: 0,
+              width: 0,
+          });
+          return;
+      }
+      var $activeTab = this.$tabs.eq(this.activeIndex);
+      if (this.isDisabled($activeTab)) {
+          return;
+      }
+      var activeTabOffset = $activeTab.offset();
+      this.$indicator.css({
+          left: ((activeTabOffset.left +
+              this.$element[0].scrollLeft -
+              this.$element[0].getBoundingClientRect().left) + "px"),
+          width: (($activeTab.innerWidth()) + "px"),
+      });
+  };
+  /**
+   * 切换到下一个选项卡
+   */
+  Tab.prototype.next = function next () {
+      if (this.activeIndex === -1) {
+          return;
+      }
+      if (this.$tabs.length > this.activeIndex + 1) {
+          this.activeIndex++;
+      }
+      else if (this.options.loop) {
+          this.activeIndex = 0;
+      }
+      this.setActive();
+  };
+  /**
+   * 切换到上一个选项卡
+   */
+  Tab.prototype.prev = function prev () {
+      if (this.activeIndex === -1) {
+          return;
+      }
+      if (this.activeIndex > 0) {
+          this.activeIndex--;
+      }
+      else if (this.options.loop) {
+          this.activeIndex = this.$tabs.length - 1;
+      }
+      this.setActive();
+  };
+  /**
+   * 显示指定索引号、或指定id的选项卡
+   * @param index 索引号、或id
+   */
+  Tab.prototype.show = function show (index) {
+          var this$1 = this;
+
+      if (this.activeIndex === -1) {
+          return;
+      }
+      if (isNumber(index)) {
+          this.activeIndex = index;
+      }
+      else {
+          this.$tabs.each(function (i, tab) {
+              if (tab.id === index) {
+                  this$1.activeIndex = i;
+                  return false;
+              }
+          });
+      }
+      this.setActive();
+  };
+  /**
+   * 在父元素的宽度变化时,需要调用该方法重新调整指示器位置
+   * 在添加或删除选项卡时,需要调用该方法
+   */
+  Tab.prototype.handleUpdate = function handleUpdate () {
+          var this$1 = this;
+
+      var $oldTabs = this.$tabs; // 旧的 tabs JQ对象
+      var $newTabs = this.$element.children('a'); // 新的 tabs JQ对象
+      var oldTabsElement = $oldTabs.get(); // 旧的 tabs 元素数组
+      var newTabsElement = $newTabs.get(); // 新的 tabs 元素数组
+      if (!$newTabs.length) {
+          this.activeIndex = -1;
+          this.$tabs = $newTabs;
+          this.setIndicatorPosition();
+          return;
+      }
+      // 重新遍历选项卡,找出新增的选项卡
+      $newTabs.each(function (index, tab) {
+          // 有新增的选项卡
+          if (oldTabsElement.indexOf(tab) < 0) {
+              this$1.bindTabEvent(tab);
+              if (this$1.activeIndex === -1) {
+                  this$1.activeIndex = 0;
+              }
+              else if (index <= this$1.activeIndex) {
+                  this$1.activeIndex++;
+              }
+          }
+      });
+      // 找出被移除的选项卡
+      $oldTabs.each(function (index, tab) {
+          // 有被移除的选项卡
+          if (newTabsElement.indexOf(tab) < 0) {
+              if (index < this$1.activeIndex) {
+                  this$1.activeIndex--;
+              }
+              else if (index === this$1.activeIndex) {
+                  this$1.activeIndex = 0;
+              }
+          }
+      });
+      this.$tabs = $newTabs;
+      this.setActive();
+  };
+  mdui.Tab = Tab;
+
+  var customAttr$5 = 'mdui-tab';
+  $(function () {
+      mdui.mutation(("[" + customAttr$5 + "]"), function () {
+          new mdui.Tab(this, parseOptions(this, customAttr$5));
+      });
+  });
+
+  /**
+   * 在桌面设备上默认显示抽屉栏,不显示遮罩层
+   * 在手机和平板设备上默认不显示抽屉栏,始终显示遮罩层,且覆盖导航栏
+   */
+  var DEFAULT_OPTIONS$5 = {
+      overlay: false,
+      swipe: false,
+  };
+  var Drawer = function Drawer(selector, options) {
+      var this$1 = this;
+      if ( options === void 0 ) options = {};
+
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS$5);
+      /**
+       * 当前是否显示着遮罩层
+       */
+      this.overlay = false;
+      this.$element = $(selector).first();
+      extend(this.options, options);
+      this.position = this.$element.hasClass('mdui-drawer-right')
+          ? 'right'
+          : 'left';
+      if (this.$element.hasClass('mdui-drawer-close')) {
+          this.state = 'closed';
+      }
+      else if (this.$element.hasClass('mdui-drawer-open')) {
+          this.state = 'opened';
+      }
+      else if (this.isDesktop()) {
+          this.state = 'opened';
+      }
+      else {
+          this.state = 'closed';
+      }
+      // 浏览器窗口大小调整时
+      $window.on('resize', $.throttle(function () {
+          if (this$1.isDesktop()) {
+              // 由手机平板切换到桌面时
+              // 如果显示着遮罩,则隐藏遮罩
+              if (this$1.overlay && !this$1.options.overlay) {
+                  $.hideOverlay();
+                  this$1.overlay = false;
+                  $.unlockScreen();
+              }
+              // 没有强制关闭,则状态为打开状态
+              if (!this$1.$element.hasClass('mdui-drawer-close')) {
+                  this$1.state = 'opened';
+              }
+          }
+          else if (!this$1.overlay && this$1.state === 'opened') {
+              // 由桌面切换到手机平板时。如果抽屉栏是打开着的且没有遮罩层,则关闭抽屉栏
+              if (this$1.$element.hasClass('mdui-drawer-open')) {
+                  $.showOverlay();
+                  this$1.overlay = true;
+                  $.lockScreen();
+                  $('.mdui-overlay').one('click', function () { return this$1.close(); });
+              }
+              else {
+                  this$1.state = 'closed';
+              }
+          }
+      }, 100));
+      // 绑定关闭按钮事件
+      this.$element.find('[mdui-drawer-close]').each(function (_, close) {
+          $(close).on('click', function () { return this$1.close(); });
+      });
+      this.swipeSupport();
+  };
+  /**
+   * 是否是桌面设备
+   */
+  Drawer.prototype.isDesktop = function isDesktop () {
+      return $window.width() >= 1024;
+  };
+  /**
+   * 滑动手势支持
+   */
+  Drawer.prototype.swipeSupport = function swipeSupport () {
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      var that = this;
+      // 抽屉栏滑动手势控制
+      var openNavEventHandler;
+      var touchStartX;
+      var touchStartY;
+      var swipeStartX;
+      var swiping = null;
+      var maybeSwiping = false;
+      var $body = $('body');
+      // 手势触发的范围
+      var swipeAreaWidth = 24;
+      function setPosition(translateX) {
+          var rtlTranslateMultiplier = that.position === 'right' ? -1 : 1;
+          var transformCSS = "translate(" + (-1 * rtlTranslateMultiplier * translateX) + "px, 0) !important;";
+          var transitionCSS = 'initial !important;';
+          that.$element.css('cssText', ("transform: " + transformCSS + "; transition: " + transitionCSS + ";"));
+      }
+      function cleanPosition() {
+          that.$element[0].style.transform = '';
+          that.$element[0].style.webkitTransform = '';
+          that.$element[0].style.transition = '';
+          that.$element[0].style.webkitTransition = '';
+      }
+      function getMaxTranslateX() {
+          return that.$element.width() + 10;
+      }
+      function getTranslateX(currentX) {
+          return Math.min(Math.max(swiping === 'closing'
+              ? swipeStartX - currentX
+              : getMaxTranslateX() + swipeStartX - currentX, 0), getMaxTranslateX());
+      }
+      function onBodyTouchEnd(event) {
+          if (swiping) {
+              var touchX = event.changedTouches[0].pageX;
+              if (that.position === 'right') {
+                  touchX = $body.width() - touchX;
+              }
+              var translateRatio = getTranslateX(touchX) / getMaxTranslateX();
+              maybeSwiping = false;
+              var swipingState = swiping;
+              swiping = null;
+              if (swipingState === 'opening') {
+                  if (translateRatio < 0.92) {
+                      cleanPosition();
+                      that.open();
+                  }
+                  else {
+                      cleanPosition();
+                  }
+              }
+              else {
+                  if (translateRatio > 0.08) {
+                      cleanPosition();
+                      that.close();
+                  }
+                  else {
+                      cleanPosition();
+                  }
+              }
+              $.unlockScreen();
+          }
+          else {
+              maybeSwiping = false;
+          }
+          $body.off({
+              // eslint-disable-next-line @typescript-eslint/no-use-before-define
+              touchmove: onBodyTouchMove,
+              touchend: onBodyTouchEnd,
+              // eslint-disable-next-line @typescript-eslint/no-use-before-define
+              touchcancel: onBodyTouchMove,
+          });
+      }
+      function onBodyTouchMove(event) {
+          var touchX = event.touches[0].pageX;
+          if (that.position === 'right') {
+              touchX = $body.width() - touchX;
+          }
+          var touchY = event.touches[0].pageY;
+          if (swiping) {
+              setPosition(getTranslateX(touchX));
+          }
+          else if (maybeSwiping) {
+              var dXAbs = Math.abs(touchX - touchStartX);
+              var dYAbs = Math.abs(touchY - touchStartY);
+              var threshold = 8;
+              if (dXAbs > threshold && dYAbs <= threshold) {
+                  swipeStartX = touchX;
+                  swiping = that.state === 'opened' ? 'closing' : 'opening';
+                  $.lockScreen();
+                  setPosition(getTranslateX(touchX));
+              }
+              else if (dXAbs <= threshold && dYAbs > threshold) {
+                  onBodyTouchEnd();
+              }
+          }
+      }
+      function onBodyTouchStart(event) {
+          touchStartX = event.touches[0].pageX;
+          if (that.position === 'right') {
+              touchStartX = $body.width() - touchStartX;
+          }
+          touchStartY = event.touches[0].pageY;
+          if (that.state !== 'opened') {
+              if (touchStartX > swipeAreaWidth ||
+                  openNavEventHandler !== onBodyTouchStart) {
+                  return;
+              }
+          }
+          maybeSwiping = true;
+          $body.on({
+              touchmove: onBodyTouchMove,
+              touchend: onBodyTouchEnd,
+              touchcancel: onBodyTouchMove,
+          });
+      }
+      function enableSwipeHandling() {
+          if (!openNavEventHandler) {
+              $body.on('touchstart', onBodyTouchStart);
+              openNavEventHandler = onBodyTouchStart;
+          }
+      }
+      if (this.options.swipe) {
+          enableSwipeHandling();
+      }
+  };
+  /**
+   * 触发组件事件
+   * @param name
+   */
+  Drawer.prototype.triggerEvent = function triggerEvent (name) {
+      componentEvent(name, 'drawer', this.$element, this);
+  };
+  /**
+   * 动画结束回调
+   */
+  Drawer.prototype.transitionEnd = function transitionEnd () {
+      if (this.$element.hasClass('mdui-drawer-open')) {
+          this.state = 'opened';
+          this.triggerEvent('opened');
+      }
+      else {
+          this.state = 'closed';
+          this.triggerEvent('closed');
+      }
+  };
+  /**
+   * 是否处于打开状态
+   */
+  Drawer.prototype.isOpen = function isOpen () {
+      return this.state === 'opening' || this.state === 'opened';
+  };
+  /**
+   * 打开抽屉栏
+   */
+  Drawer.prototype.open = function open () {
+          var this$1 = this;
+
+      if (this.isOpen()) {
+          return;
+      }
+      this.state = 'opening';
+      this.triggerEvent('open');
+      if (!this.options.overlay) {
+          $('body').addClass(("mdui-drawer-body-" + (this.position)));
+      }
+      this.$element
+          .removeClass('mdui-drawer-close')
+          .addClass('mdui-drawer-open')
+          .transitionEnd(function () { return this$1.transitionEnd(); });
+      if (!this.isDesktop() || this.options.overlay) {
+          this.overlay = true;
+          $.showOverlay().one('click', function () { return this$1.close(); });
+          $.lockScreen();
+      }
+  };
+  /**
+   * 关闭抽屉栏
+   */
+  Drawer.prototype.close = function close () {
+          var this$1 = this;
+
+      if (!this.isOpen()) {
+          return;
+      }
+      this.state = 'closing';
+      this.triggerEvent('close');
+      if (!this.options.overlay) {
+          $('body').removeClass(("mdui-drawer-body-" + (this.position)));
+      }
+      this.$element
+          .addClass('mdui-drawer-close')
+          .removeClass('mdui-drawer-open')
+          .transitionEnd(function () { return this$1.transitionEnd(); });
+      if (this.overlay) {
+          $.hideOverlay();
+          this.overlay = false;
+          $.unlockScreen();
+      }
+  };
+  /**
+   * 切换抽屉栏打开/关闭状态
+   */
+  Drawer.prototype.toggle = function toggle () {
+      this.isOpen() ? this.close() : this.open();
+  };
+  /**
+   * 返回当前抽屉栏的状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+   */
+  Drawer.prototype.getState = function getState () {
+      return this.state;
+  };
+  mdui.Drawer = Drawer;
+
+  var customAttr$6 = 'mdui-drawer';
+  $(function () {
+      mdui.mutation(("[" + customAttr$6 + "]"), function () {
+          var $element = $(this);
+          var options = parseOptions(this, customAttr$6);
+          var selector = options.target;
+          // @ts-ignore
+          delete options.target;
+          var $drawer = $(selector).first();
+          var instance = new mdui.Drawer($drawer, options);
+          $element.on('click', function () { return instance.toggle(); });
+      });
+  });
+
+  var container = {};
+  function queue(name, func) {
+      if (isUndefined(container[name])) {
+          container[name] = [];
+      }
+      if (isUndefined(func)) {
+          return container[name];
+      }
+      container[name].push(func);
+  }
+  /**
+   * 从队列中移除第一个函数,并执行该函数
+   * @param name 队列满
+   */
+  function dequeue(name) {
+      if (isUndefined(container[name])) {
+          return;
+      }
+      if (!container[name].length) {
+          return;
+      }
+      var func = container[name].shift();
+      func();
+  }
+
+  var DEFAULT_OPTIONS$6 = {
+      history: true,
+      overlay: true,
+      modal: false,
+      closeOnEsc: true,
+      closeOnCancel: true,
+      closeOnConfirm: true,
+      destroyOnClosed: false,
+  };
+  /**
+   * 当前显示的对话框实例
+   */
+  var currentInst = null;
+  /**
+   * 队列名
+   */
+  var queueName = '_mdui_dialog';
+  /**
+   * 窗口是否已锁定
+   */
+  var isLockScreen = false;
+  /**
+   * 遮罩层元素
+   */
+  var $overlay;
+  var Dialog = function Dialog(selector, options) {
+      var this$1 = this;
+      if ( options === void 0 ) options = {};
+
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS$6);
+      /**
+       * 当前 dialog 的状态
+       */
+      this.state = 'closed';
+      /**
+       * dialog 元素是否是动态添加的
+       */
+      this.append = false;
+      this.$element = $(selector).first();
+      // 如果对话框元素没有在当前文档中,则需要添加
+      if (!contains(document.body, this.$element[0])) {
+          this.append = true;
+          $('body').append(this.$element);
+      }
+      extend(this.options, options);
+      // 绑定取消按钮事件
+      this.$element.find('[mdui-dialog-cancel]').each(function (_, cancel) {
+          $(cancel).on('click', function () {
+              this$1.triggerEvent('cancel');
+              if (this$1.options.closeOnCancel) {
+                  this$1.close();
+              }
+          });
+      });
+      // 绑定确认按钮事件
+      this.$element.find('[mdui-dialog-confirm]').each(function (_, confirm) {
+          $(confirm).on('click', function () {
+              this$1.triggerEvent('confirm');
+              if (this$1.options.closeOnConfirm) {
+                  this$1.close();
+              }
+          });
+      });
+      // 绑定关闭按钮事件
+      this.$element.find('[mdui-dialog-close]').each(function (_, close) {
+          $(close).on('click', function () { return this$1.close(); });
+      });
+  };
+  /**
+   * 触发组件事件
+   * @param name
+   */
+  Dialog.prototype.triggerEvent = function triggerEvent (name) {
+      componentEvent(name, 'dialog', this.$element, this);
+  };
+  /**
+   * 窗口宽度变化,或对话框内容变化时,调整对话框位置和对话框内的滚动条
+   */
+  Dialog.prototype.readjust = function readjust () {
+      if (!currentInst) {
+          return;
+      }
+      var $element = currentInst.$element;
+      var $title = $element.children('.mdui-dialog-title');
+      var $content = $element.children('.mdui-dialog-content');
+      var $actions = $element.children('.mdui-dialog-actions');
+      // 调整 dialog 的 top 和 height 值
+      $element.height('');
+      $content.height('');
+      var elementHeight = $element.height();
+      $element.css({
+          top: ((($window.height() - elementHeight) / 2) + "px"),
+          height: (elementHeight + "px"),
+      });
+      // 调整 mdui-dialog-content 的高度
+      $content.innerHeight(elementHeight -
+          ($title.innerHeight() || 0) -
+          ($actions.innerHeight() || 0));
+  };
+  /**
+   * hashchange 事件触发时关闭对话框
+   */
+  Dialog.prototype.hashchangeEvent = function hashchangeEvent () {
+      if (window.location.hash.substring(1).indexOf('mdui-dialog') < 0) {
+          currentInst.close(true);
+      }
+  };
+  /**
+   * 点击遮罩层关闭对话框
+   * @param event
+   */
+  Dialog.prototype.overlayClick = function overlayClick (event) {
+      if ($(event.target).hasClass('mdui-overlay') &&
+          currentInst) {
+          currentInst.close();
+      }
+  };
+  /**
+   * 动画结束回调
+   */
+  Dialog.prototype.transitionEnd = function transitionEnd () {
+      if (this.$element.hasClass('mdui-dialog-open')) {
+          this.state = 'opened';
+          this.triggerEvent('opened');
+      }
+      else {
+          this.state = 'closed';
+          this.triggerEvent('closed');
+          this.$element.hide();
+          // 所有对话框都关闭,且当前没有打开的对话框时,解锁屏幕
+          if (!queue(queueName).length && !currentInst && isLockScreen) {
+              $.unlockScreen();
+              isLockScreen = false;
+          }
+          $window.off('resize', $.throttle(this.readjust, 100));
+          if (this.options.destroyOnClosed) {
+              this.destroy();
+          }
+      }
+  };
+  /**
+   * 打开指定对话框
+   */
+  Dialog.prototype.doOpen = function doOpen () {
+          var this$1 = this;
+
+      currentInst = this;
+      if (!isLockScreen) {
+          $.lockScreen();
+          isLockScreen = true;
+      }
+      this.$element.show();
+      this.readjust();
+      $window.on('resize', $.throttle(this.readjust, 100));
+      // 打开消息框
+      this.state = 'opening';
+      this.triggerEvent('open');
+      this.$element
+          .addClass('mdui-dialog-open')
+          .transitionEnd(function () { return this$1.transitionEnd(); });
+      // 不存在遮罩层元素时,添加遮罩层
+      if (!$overlay) {
+          $overlay = $.showOverlay(5100);
+      }
+      // 点击遮罩层时是否关闭对话框
+      if (this.options.modal) {
+          $overlay.off('click', this.overlayClick);
+      }
+      else {
+          $overlay.on('click', this.overlayClick);
+      }
+      // 是否显示遮罩层,不显示时,把遮罩层背景透明
+      $overlay.css('opacity', this.options.overlay ? '' : 0);
+      if (this.options.history) {
+          // 如果 hash 中原来就有 mdui-dialog,先删除,避免后退历史纪录后仍然有 mdui-dialog 导致无法关闭
+          // 包括 mdui-dialog 和 &mdui-dialog 和 ?mdui-dialog
+          var hash = window.location.hash.substring(1);
+          if (hash.indexOf('mdui-dialog') > -1) {
+              hash = hash.replace(/[&?]?mdui-dialog/g, '');
+          }
+          // 后退按钮关闭对话框
+          if (hash) {
+              window.location.hash = "" + hash + (hash.indexOf('?') > -1 ? '&' : '?') + "mdui-dialog";
+          }
+          else {
+              window.location.hash = 'mdui-dialog';
+          }
+          $window.on('hashchange', this.hashchangeEvent);
+      }
+  };
+  /**
+   * 当前对话框是否为打开状态
+   */
+  Dialog.prototype.isOpen = function isOpen () {
+      return this.state === 'opening' || this.state === 'opened';
+  };
+  /**
+   * 打开对话框
+   */
+  Dialog.prototype.open = function open () {
+          var this$1 = this;
+
+      if (this.isOpen()) {
+          return;
+      }
+      // 如果当前有正在打开或已经打开的对话框,或队列不为空,则先加入队列,等旧对话框开始关闭时再打开
+      if ((currentInst &&
+          (currentInst.state === 'opening' || currentInst.state === 'opened')) ||
+          queue(queueName).length) {
+          queue(queueName, function () { return this$1.doOpen(); });
+          return;
+      }
+      this.doOpen();
+  };
+  /**
+   * 关闭对话框
+   */
+  Dialog.prototype.close = function close (historyBack) {
+          var this$1 = this;
+          if ( historyBack === void 0 ) historyBack = false;
+
+      // historyBack 是否需要后退历史纪录,默认为 `false`。该参数仅内部使用
+      // 为 `false` 时是通过 js 关闭,需要后退一个历史记录
+      // 为 `true` 时是通过后退按钮关闭,不需要后退历史记录
+      // setTimeout 的作用是:
+      // 当同时关闭一个对话框,并打开另一个对话框时,使打开对话框的操作先执行,以使需要打开的对话框先加入队列
+      setTimeout(function () {
+          if (!this$1.isOpen()) {
+              return;
+          }
+          currentInst = null;
+          this$1.state = 'closing';
+          this$1.triggerEvent('close');
+          // 所有对话框都关闭,且当前没有打开的对话框时,隐藏遮罩
+          if (!queue(queueName).length && $overlay) {
+              $.hideOverlay();
+              $overlay = null;
+              // 若仍存在遮罩,恢复遮罩的 z-index
+              $('.mdui-overlay').css('z-index', 2000);
+          }
+          this$1.$element
+              .removeClass('mdui-dialog-open')
+              .transitionEnd(function () { return this$1.transitionEnd(); });
+          if (this$1.options.history && !queue(queueName).length) {
+              if (!historyBack) {
+                  window.history.back();
+              }
+              $window.off('hashchange', this$1.hashchangeEvent);
+          }
+          // 关闭旧对话框,打开新对话框。
+          // 加一点延迟,仅仅为了视觉效果更好。不加延时也不影响功能
+          setTimeout(function () {
+              dequeue(queueName);
+          }, 100);
+      });
+  };
+  /**
+   * 切换对话框打开/关闭状态
+   */
+  Dialog.prototype.toggle = function toggle () {
+      this.isOpen() ? this.close() : this.open();
+  };
+  /**
+   * 获取对话框状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+   */
+  Dialog.prototype.getState = function getState () {
+      return this.state;
+  };
+  /**
+   * 销毁对话框
+   */
+  Dialog.prototype.destroy = function destroy () {
+      if (this.append) {
+          this.$element.remove();
+      }
+      if (!queue(queueName).length && !currentInst) {
+          if ($overlay) {
+              $.hideOverlay();
+              $overlay = null;
+          }
+          if (isLockScreen) {
+              $.unlockScreen();
+              isLockScreen = false;
+          }
+      }
+  };
+  /**
+   * 对话框内容变化时,需要调用该方法来调整对话框位置和滚动条高度
+   */
+  Dialog.prototype.handleUpdate = function handleUpdate () {
+      this.readjust();
+  };
+
+  // esc 按下时关闭对话框
+  $document.on('keydown', function (event) {
+      if (currentInst &&
+          currentInst.options.closeOnEsc &&
+          currentInst.state === 'opened' &&
+          event.keyCode === 27) {
+          currentInst.close();
+      }
+  });
+  mdui.Dialog = Dialog;
+
+  var customAttr$7 = 'mdui-dialog';
+  var dataName$1 = '_mdui_dialog';
+  $(function () {
+      $document.on('click', ("[" + customAttr$7 + "]"), function () {
+          var options = parseOptions(this, customAttr$7);
+          var selector = options.target;
+          // @ts-ignore
+          delete options.target;
+          var $dialog = $(selector).first();
+          var instance = $dialog.data(dataName$1);
+          if (!instance) {
+              instance = new mdui.Dialog($dialog, options);
+              $dialog.data(dataName$1, instance);
+          }
+          instance.open();
+      });
+  });
+
+  var DEFAULT_BUTTON = {
+      text: '',
+      bold: false,
+      close: true,
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onClick: function () { },
+  };
+  var DEFAULT_OPTIONS$7 = {
+      title: '',
+      content: '',
+      buttons: [],
+      stackedButtons: false,
+      cssClass: '',
+      history: true,
+      overlay: true,
+      modal: false,
+      closeOnEsc: true,
+      destroyOnClosed: true,
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onOpen: function () { },
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onOpened: function () { },
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onClose: function () { },
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onClosed: function () { },
+  };
+  mdui.dialog = function (options) {
+      var _a, _b;
+      // 合并配置参数
+      options = extend({}, DEFAULT_OPTIONS$7, options);
+      each(options.buttons, function (i, button) {
+          options.buttons[i] = extend({}, DEFAULT_BUTTON, button);
+      });
+      // 按钮的 HTML
+      var buttonsHTML = '';
+      if ((_a = options.buttons) === null || _a === void 0 ? void 0 : _a.length) {
+          buttonsHTML = "<div class=\"mdui-dialog-actions" + (options.stackedButtons ? ' mdui-dialog-actions-stacked' : '') + "\">";
+          each(options.buttons, function (_, button) {
+              buttonsHTML +=
+                  '<a href="javascript:void(0)" ' +
+                      "class=\"mdui-btn mdui-ripple mdui-text-color-primary " + (button.bold ? 'mdui-btn-bold' : '') + "\">" + (button.text) + "</a>";
+          });
+          buttonsHTML += '</div>';
+      }
+      // Dialog 的 HTML
+      var HTML = "<div class=\"mdui-dialog " + (options.cssClass) + "\">" +
+          (options.title
+              ? ("<div class=\"mdui-dialog-title\">" + (options.title) + "</div>")
+              : '') +
+          (options.content
+              ? ("<div class=\"mdui-dialog-content\">" + (options.content) + "</div>")
+              : '') +
+          buttonsHTML +
+          '</div>';
+      // 实例化 Dialog
+      var instance = new mdui.Dialog(HTML, {
+          history: options.history,
+          overlay: options.overlay,
+          modal: options.modal,
+          closeOnEsc: options.closeOnEsc,
+          destroyOnClosed: options.destroyOnClosed,
+      });
+      // 绑定按钮事件
+      if ((_b = options.buttons) === null || _b === void 0 ? void 0 : _b.length) {
+          instance.$element
+              .find('.mdui-dialog-actions .mdui-btn')
+              .each(function (index, button) {
+              $(button).on('click', function () {
+                  options.buttons[index].onClick(instance);
+                  if (options.buttons[index].close) {
+                      instance.close();
+                  }
+              });
+          });
+      }
+      // 绑定打开关闭事件
+      instance.$element
+          .on('open.mdui.dialog', function () {
+          options.onOpen(instance);
+      })
+          .on('opened.mdui.dialog', function () {
+          options.onOpened(instance);
+      })
+          .on('close.mdui.dialog', function () {
+          options.onClose(instance);
+      })
+          .on('closed.mdui.dialog', function () {
+          options.onClosed(instance);
+      });
+      instance.open();
+      return instance;
+  };
+
+  var DEFAULT_OPTIONS$8 = {
+      confirmText: 'ok',
+      history: true,
+      modal: false,
+      closeOnEsc: true,
+      closeOnConfirm: true,
+  };
+  mdui.alert = function (text, title, onConfirm, options) {
+      if (isFunction(title)) {
+          options = onConfirm;
+          onConfirm = title;
+          title = '';
+      }
+      if (isUndefined(onConfirm)) {
+          // eslint-disable-next-line @typescript-eslint/no-empty-function
+          onConfirm = function () { };
+      }
+      if (isUndefined(options)) {
+          options = {};
+      }
+      options = extend({}, DEFAULT_OPTIONS$8, options);
+      return mdui.dialog({
+          title: title,
+          content: text,
+          buttons: [
+              {
+                  text: options.confirmText,
+                  bold: false,
+                  close: options.closeOnConfirm,
+                  onClick: onConfirm,
+              } ],
+          cssClass: 'mdui-dialog-alert',
+          history: options.history,
+          modal: options.modal,
+          closeOnEsc: options.closeOnEsc,
+      });
+  };
+
+  var DEFAULT_OPTIONS$9 = {
+      confirmText: 'ok',
+      cancelText: 'cancel',
+      history: true,
+      modal: false,
+      closeOnEsc: true,
+      closeOnCancel: true,
+      closeOnConfirm: true,
+  };
+  mdui.confirm = function (text, title, onConfirm, onCancel, options) {
+      if (isFunction(title)) {
+          options = onCancel;
+          onCancel = onConfirm;
+          onConfirm = title;
+          title = '';
+      }
+      if (isUndefined(onConfirm)) {
+          // eslint-disable-next-line @typescript-eslint/no-empty-function
+          onConfirm = function () { };
+      }
+      if (isUndefined(onCancel)) {
+          // eslint-disable-next-line @typescript-eslint/no-empty-function
+          onCancel = function () { };
+      }
+      if (isUndefined(options)) {
+          options = {};
+      }
+      options = extend({}, DEFAULT_OPTIONS$9, options);
+      return mdui.dialog({
+          title: title,
+          content: text,
+          buttons: [
+              {
+                  text: options.cancelText,
+                  bold: false,
+                  close: options.closeOnCancel,
+                  onClick: onCancel,
+              },
+              {
+                  text: options.confirmText,
+                  bold: false,
+                  close: options.closeOnConfirm,
+                  onClick: onConfirm,
+              } ],
+          cssClass: 'mdui-dialog-confirm',
+          history: options.history,
+          modal: options.modal,
+          closeOnEsc: options.closeOnEsc,
+      });
+  };
+
+  var DEFAULT_OPTIONS$a = {
+      confirmText: 'ok',
+      cancelText: 'cancel',
+      history: true,
+      modal: false,
+      closeOnEsc: true,
+      closeOnCancel: true,
+      closeOnConfirm: true,
+      type: 'text',
+      maxlength: 0,
+      defaultValue: '',
+      confirmOnEnter: false,
+  };
+  mdui.prompt = function (label, title, onConfirm, onCancel, options) {
+      if (isFunction(title)) {
+          options = onCancel;
+          onCancel = onConfirm;
+          onConfirm = title;
+          title = '';
+      }
+      if (isUndefined(onConfirm)) {
+          // eslint-disable-next-line @typescript-eslint/no-empty-function
+          onConfirm = function () { };
+      }
+      if (isUndefined(onCancel)) {
+          // eslint-disable-next-line @typescript-eslint/no-empty-function
+          onCancel = function () { };
+      }
+      if (isUndefined(options)) {
+          options = {};
+      }
+      options = extend({}, DEFAULT_OPTIONS$a, options);
+      var content = '<div class="mdui-textfield">' +
+          (label ? ("<label class=\"mdui-textfield-label\">" + label + "</label>") : '') +
+          (options.type === 'text'
+              ? ("<input class=\"mdui-textfield-input\" type=\"text\" value=\"" + (options.defaultValue) + "\" " + (options.maxlength ? 'maxlength="' + options.maxlength + '"' : '') + "/>")
+              : '') +
+          (options.type === 'textarea'
+              ? ("<textarea class=\"mdui-textfield-input\" " + (options.maxlength ? 'maxlength="' + options.maxlength + '"' : '') + ">" + (options.defaultValue) + "</textarea>")
+              : '') +
+          '</div>';
+      var onCancelClick = function (dialog) {
+          var value = dialog.$element.find('.mdui-textfield-input').val();
+          onCancel(value, dialog);
+      };
+      var onConfirmClick = function (dialog) {
+          var value = dialog.$element.find('.mdui-textfield-input').val();
+          onConfirm(value, dialog);
+      };
+      return mdui.dialog({
+          title: title,
+          content: content,
+          buttons: [
+              {
+                  text: options.cancelText,
+                  bold: false,
+                  close: options.closeOnCancel,
+                  onClick: onCancelClick,
+              },
+              {
+                  text: options.confirmText,
+                  bold: false,
+                  close: options.closeOnConfirm,
+                  onClick: onConfirmClick,
+              } ],
+          cssClass: 'mdui-dialog-prompt',
+          history: options.history,
+          modal: options.modal,
+          closeOnEsc: options.closeOnEsc,
+          onOpen: function (dialog) {
+              // 初始化输入框
+              var $input = dialog.$element.find('.mdui-textfield-input');
+              mdui.updateTextFields($input);
+              // 聚焦到输入框
+              $input[0].focus();
+              // 捕捉文本框回车键,在单行文本框的情况下触发回调
+              if (options.type !== 'textarea' && options.confirmOnEnter === true) {
+                  $input.on('keydown', function (event) {
+                      if (event.keyCode === 13) {
+                          var value = dialog.$element.find('.mdui-textfield-input').val();
+                          onConfirm(value, dialog);
+                          if (options.closeOnConfirm) {
+                              dialog.close();
+                          }
+                          return false;
+                      }
+                      return;
+                  });
+              }
+              // 如果是多行输入框,监听输入框的 input 事件,更新对话框高度
+              if (options.type === 'textarea') {
+                  $input.on('input', function () { return dialog.handleUpdate(); });
+              }
+              // 有字符数限制时,加载完文本框后 DOM 会变化,需要更新对话框高度
+              if (options.maxlength) {
+                  dialog.handleUpdate();
+              }
+          },
+      });
+  };
+
+  var DEFAULT_OPTIONS$b = {
+      position: 'auto',
+      delay: 0,
+      content: '',
+  };
+  var Tooltip = function Tooltip(selector, options) {
+      if ( options === void 0 ) options = {};
+
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS$b);
+      /**
+       * 当前 tooltip 的状态
+       */
+      this.state = 'closed';
+      /**
+       * setTimeout 的返回值
+       */
+      this.timeoutId = null;
+      this.$target = $(selector).first();
+      extend(this.options, options);
+      // 创建 Tooltip HTML
+      this.$element = $(("<div class=\"mdui-tooltip\" id=\"" + ($.guid()) + "\">" + (this.options.content) + "</div>")).appendTo(document.body);
+      // 绑定事件。元素处于 disabled 状态时无法触发鼠标事件,为了统一,把 touch 事件也禁用
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      var that = this;
+      this.$target
+          .on('touchstart mouseenter', function (event) {
+          if (that.isDisabled(this)) {
+              return;
+          }
+          if (!isAllow(event)) {
+              return;
+          }
+          register(event);
+          that.open();
+      })
+          .on('touchend mouseleave', function (event) {
+          if (that.isDisabled(this)) {
+              return;
+          }
+          if (!isAllow(event)) {
+              return;
+          }
+          that.close();
+      })
+          .on(unlockEvent, function (event) {
+          if (that.isDisabled(this)) {
+              return;
+          }
+          register(event);
+      });
+  };
+  /**
+   * 元素是否已禁用
+   * @param element
+   */
+  Tooltip.prototype.isDisabled = function isDisabled (element) {
+      return (element.disabled ||
+          $(element).attr('disabled') !== undefined);
+  };
+  /**
+   * 是否是桌面设备
+   */
+  Tooltip.prototype.isDesktop = function isDesktop () {
+      return $window.width() > 1024;
+  };
+  /**
+   * 设置 Tooltip 的位置
+   */
+  Tooltip.prototype.setPosition = function setPosition () {
+      var marginLeft;
+      var marginTop;
+      // 触发的元素
+      var targetProps = this.$target[0].getBoundingClientRect();
+      // 触发的元素和 Tooltip 之间的距离
+      var targetMargin = this.isDesktop() ? 14 : 24;
+      // Tooltip 的宽度和高度
+      var tooltipWidth = this.$element[0].offsetWidth;
+      var tooltipHeight = this.$element[0].offsetHeight;
+      // Tooltip 的方向
+      var position = this.options.position;
+      // 自动判断位置,加 2px,使 Tooltip 距离窗口边框至少有 2px 的间距
+      if (position === 'auto') {
+          if (targetProps.top +
+              targetProps.height +
+              targetMargin +
+              tooltipHeight +
+              2 <
+              $window.height()) {
+              position = 'bottom';
+          }
+          else if (targetMargin + tooltipHeight + 2 < targetProps.top) {
+              position = 'top';
+          }
+          else if (targetMargin + tooltipWidth + 2 < targetProps.left) {
+              position = 'left';
+          }
+          else if (targetProps.width + targetMargin + tooltipWidth + 2 <
+              $window.width() - targetProps.left) {
+              position = 'right';
+          }
+          else {
+              position = 'bottom';
+          }
+      }
+      // 设置位置
+      switch (position) {
+          case 'bottom':
+              marginLeft = -1 * (tooltipWidth / 2);
+              marginTop = targetProps.height / 2 + targetMargin;
+              this.$element.transformOrigin('top center');
+              break;
+          case 'top':
+              marginLeft = -1 * (tooltipWidth / 2);
+              marginTop =
+                  -1 * (tooltipHeight + targetProps.height / 2 + targetMargin);
+              this.$element.transformOrigin('bottom center');
+              break;
+          case 'left':
+              marginLeft = -1 * (tooltipWidth + targetProps.width / 2 + targetMargin);
+              marginTop = -1 * (tooltipHeight / 2);
+              this.$element.transformOrigin('center right');
+              break;
+          case 'right':
+              marginLeft = targetProps.width / 2 + targetMargin;
+              marginTop = -1 * (tooltipHeight / 2);
+              this.$element.transformOrigin('center left');
+              break;
+      }
+      var targetOffset = this.$target.offset();
+      this.$element.css({
+          top: ((targetOffset.top + targetProps.height / 2) + "px"),
+          left: ((targetOffset.left + targetProps.width / 2) + "px"),
+          'margin-left': (marginLeft + "px"),
+          'margin-top': (marginTop + "px"),
+      });
+  };
+  /**
+   * 触发组件事件
+   * @param name
+   */
+  Tooltip.prototype.triggerEvent = function triggerEvent (name) {
+      componentEvent(name, 'tooltip', this.$target, this);
+  };
+  /**
+   * 动画结束回调
+   */
+  Tooltip.prototype.transitionEnd = function transitionEnd () {
+      if (this.$element.hasClass('mdui-tooltip-open')) {
+          this.state = 'opened';
+          this.triggerEvent('opened');
+      }
+      else {
+          this.state = 'closed';
+          this.triggerEvent('closed');
+      }
+  };
+  /**
+   * 当前 tooltip 是否为打开状态
+   */
+  Tooltip.prototype.isOpen = function isOpen () {
+      return this.state === 'opening' || this.state === 'opened';
+  };
+  /**
+   * 执行打开 tooltip
+   */
+  Tooltip.prototype.doOpen = function doOpen () {
+          var this$1 = this;
+
+      this.state = 'opening';
+      this.triggerEvent('open');
+      this.$element
+          .addClass('mdui-tooltip-open')
+          .transitionEnd(function () { return this$1.transitionEnd(); });
+  };
+  /**
+   * 打开 Tooltip
+   * @param options 允许每次打开时设置不同的参数
+   */
+  Tooltip.prototype.open = function open (options) {
+          var this$1 = this;
+
+      if (this.isOpen()) {
+          return;
+      }
+      var oldOptions = extend({}, this.options);
+      if (options) {
+          extend(this.options, options);
+      }
+      // tooltip 的内容有更新
+      if (oldOptions.content !== this.options.content) {
+          this.$element.html(this.options.content);
+      }
+      this.setPosition();
+      if (this.options.delay) {
+          this.timeoutId = setTimeout(function () { return this$1.doOpen(); }, this.options.delay);
+      }
+      else {
+          this.timeoutId = null;
+          this.doOpen();
+      }
+  };
+  /**
+   * 关闭 Tooltip
+   */
+  Tooltip.prototype.close = function close () {
+          var this$1 = this;
+
+      if (this.timeoutId) {
+          clearTimeout(this.timeoutId);
+          this.timeoutId = null;
+      }
+      if (!this.isOpen()) {
+          return;
+      }
+      this.state = 'closing';
+      this.triggerEvent('close');
+      this.$element
+          .removeClass('mdui-tooltip-open')
+          .transitionEnd(function () { return this$1.transitionEnd(); });
+  };
+  /**
+   * 切换 Tooltip 的打开状态
+   */
+  Tooltip.prototype.toggle = function toggle () {
+      this.isOpen() ? this.close() : this.open();
+  };
+  /**
+   * 获取 Tooltip 状态。共包含四种状态:`opening`、`opened`、`closing`、`closed`
+   */
+  Tooltip.prototype.getState = function getState () {
+      return this.state;
+  };
+  mdui.Tooltip = Tooltip;
+
+  var customAttr$8 = 'mdui-tooltip';
+  var dataName$2 = '_mdui_tooltip';
+  $(function () {
+      // mouseenter 不能冒泡,所以这里用 mouseover 代替
+      $document.on('touchstart mouseover', ("[" + customAttr$8 + "]"), function () {
+          var $target = $(this);
+          var instance = $target.data(dataName$2);
+          if (!instance) {
+              instance = new mdui.Tooltip(this, parseOptions(this, customAttr$8));
+              $target.data(dataName$2, instance);
+          }
+      });
+  });
+
+  var DEFAULT_OPTIONS$c = {
+      message: '',
+      timeout: 4000,
+      position: 'bottom',
+      buttonText: '',
+      buttonColor: '',
+      closeOnButtonClick: true,
+      closeOnOutsideClick: true,
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onClick: function () { },
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onButtonClick: function () { },
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onOpen: function () { },
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onOpened: function () { },
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onClose: function () { },
+      // eslint-disable-next-line @typescript-eslint/no-empty-function
+      onClosed: function () { },
+  };
+  /**
+   * 当前打开着的 Snackbar
+   */
+  var currentInst$1 = null;
+  /**
+   * 队列名
+   */
+  var queueName$1 = '_mdui_snackbar';
+  var Snackbar = function Snackbar(options) {
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS$c);
+      /**
+       * 当前 Snackbar 的状态
+       */
+      this.state = 'closed';
+      /**
+       * setTimeout 的 ID
+       */
+      this.timeoutId = null;
+      extend(this.options, options);
+      // 按钮颜色
+      var buttonColorStyle = '';
+      var buttonColorClass = '';
+      if (this.options.buttonColor.indexOf('#') === 0 ||
+          this.options.buttonColor.indexOf('rgb') === 0) {
+          buttonColorStyle = "style=\"color:" + (this.options.buttonColor) + "\"";
+      }
+      else if (this.options.buttonColor !== '') {
+          buttonColorClass = "mdui-text-color-" + (this.options.buttonColor);
+      }
+      // 添加 HTML
+      this.$element = $('<div class="mdui-snackbar">' +
+          "<div class=\"mdui-snackbar-text\">" + (this.options.message) + "</div>" +
+          (this.options.buttonText
+              ? ("<a href=\"javascript:void(0)\" class=\"mdui-snackbar-action mdui-btn mdui-ripple mdui-ripple-white " + buttonColorClass + "\" " + buttonColorStyle + ">" + (this.options.buttonText) + "</a>")
+              : '') +
+          '</div>').appendTo(document.body);
+      // 设置位置
+      this.setPosition('close');
+      this.$element.reflow().addClass(("mdui-snackbar-" + (this.options.position)));
+  };
+  /**
+   * 点击 Snackbar 外面的区域关闭
+   * @param event
+   */
+  Snackbar.prototype.closeOnOutsideClick = function closeOnOutsideClick (event) {
+      var $target = $(event.target);
+      if (!$target.hasClass('mdui-snackbar') &&
+          !$target.parents('.mdui-snackbar').length) {
+          currentInst$1.close();
+      }
+  };
+  /**
+   * 设置 Snackbar 的位置
+   * @param state
+   */
+  Snackbar.prototype.setPosition = function setPosition (state) {
+      var snackbarHeight = this.$element[0].clientHeight;
+      var position = this.options.position;
+      var translateX;
+      var translateY;
+      // translateX
+      if (position === 'bottom' || position === 'top') {
+          translateX = '-50%';
+      }
+      else {
+          translateX = '0';
+      }
+      // translateY
+      if (state === 'open') {
+          translateY = '0';
+      }
+      else {
+          if (position === 'bottom') {
+              translateY = snackbarHeight;
+          }
+          if (position === 'top') {
+              translateY = -snackbarHeight;
+          }
+          if (position === 'left-top' || position === 'right-top') {
+              translateY = -snackbarHeight - 24;
+          }
+          if (position === 'left-bottom' || position === 'right-bottom') {
+              translateY = snackbarHeight + 24;
+          }
+      }
+      this.$element.transform(("translate(" + translateX + "," + translateY + "px"));
+  };
+  /**
+   * 打开 Snackbar
+   */
+  Snackbar.prototype.open = function open () {
+          var this$1 = this;
+
+      if (this.state === 'opening' || this.state === 'opened') {
+          return;
+      }
+      // 如果当前有正在显示的 Snackbar,则先加入队列,等旧 Snackbar 关闭后再打开
+      if (currentInst$1) {
+          queue(queueName$1, function () { return this$1.open(); });
+          return;
+      }
+      currentInst$1 = this;
+      // 开始打开
+      this.state = 'opening';
+      this.options.onOpen(this);
+      this.setPosition('open');
+      this.$element.transitionEnd(function () {
+          if (this$1.state !== 'opening') {
+              return;
+          }
+          this$1.state = 'opened';
+          this$1.options.onOpened(this$1);
+          // 有按钮时绑定事件
+          if (this$1.options.buttonText) {
+              this$1.$element.find('.mdui-snackbar-action').on('click', function () {
+                  this$1.options.onButtonClick(this$1);
+                  if (this$1.options.closeOnButtonClick) {
+                      this$1.close();
+                  }
+              });
+          }
+          // 点击 snackbar 的事件
+          this$1.$element.on('click', function (event) {
+              if (!$(event.target).hasClass('mdui-snackbar-action')) {
+                  this$1.options.onClick(this$1);
+              }
+          });
+          // 点击 Snackbar 外面的区域关闭
+          if (this$1.options.closeOnOutsideClick) {
+              $document.on(startEvent, this$1.closeOnOutsideClick);
+          }
+          // 超时后自动关闭
+          if (this$1.options.timeout) {
+              this$1.timeoutId = setTimeout(function () { return this$1.close(); }, this$1.options.timeout);
+          }
+      });
+  };
+  /**
+   * 关闭 Snackbar
+   */
+  Snackbar.prototype.close = function close () {
+          var this$1 = this;
+
+      if (this.state === 'closing' || this.state === 'closed') {
+          return;
+      }
+      if (this.timeoutId) {
+          clearTimeout(this.timeoutId);
+      }
+      if (this.options.closeOnOutsideClick) {
+          $document.off(startEvent, this.closeOnOutsideClick);
+      }
+      this.state = 'closing';
+      this.options.onClose(this);
+      this.setPosition('close');
+      this.$element.transitionEnd(function () {
+          if (this$1.state !== 'closing') {
+              return;
+          }
+          currentInst$1 = null;
+          this$1.state = 'closed';
+          this$1.options.onClosed(this$1);
+          this$1.$element.remove();
+          dequeue(queueName$1);
+      });
+  };
+  mdui.snackbar = function (message, options) {
+      if ( options === void 0 ) options = {};
+
+      if (isString(message)) {
+          options.message = message;
+      }
+      else {
+          options = message;
+      }
+      var instance = new Snackbar(options);
+      instance.open();
+      return instance;
+  };
+
+  $(function () {
+      // 切换导航项
+      $document.on('click', '.mdui-bottom-nav>a', function () {
+          var $item = $(this);
+          var $bottomNav = $item.parent();
+          $bottomNav.children('a').each(function (index, item) {
+              var isThis = $item.is(item);
+              if (isThis) {
+                  componentEvent('change', 'bottomNav', $bottomNav[0], undefined, {
+                      index: index,
+                  });
+              }
+              isThis
+                  ? $(item).addClass('mdui-bottom-nav-active')
+                  : $(item).removeClass('mdui-bottom-nav-active');
+          });
+      });
+      // 滚动时隐藏 mdui-bottom-nav-scroll-hide
+      mdui.mutation('.mdui-bottom-nav-scroll-hide', function () {
+          new mdui.Headroom(this, {
+              pinnedClass: 'mdui-headroom-pinned-down',
+              unpinnedClass: 'mdui-headroom-unpinned-down',
+          });
+      });
+  });
+
+  /**
+   * layer 的 HTML 结构
+   * @param index
+   */
+  function layerHTML(index) {
+      if ( index === void 0 ) index = false;
+
+      return ("<div class=\"mdui-spinner-layer " + (index ? ("mdui-spinner-layer-" + index) : '') + "\">" +
+          '<div class="mdui-spinner-circle-clipper mdui-spinner-left">' +
+          '<div class="mdui-spinner-circle"></div>' +
+          '</div>' +
+          '<div class="mdui-spinner-gap-patch">' +
+          '<div class="mdui-spinner-circle"></div>' +
+          '</div>' +
+          '<div class="mdui-spinner-circle-clipper mdui-spinner-right">' +
+          '<div class="mdui-spinner-circle"></div>' +
+          '</div>' +
+          '</div>');
+  }
+  /**
+   * 填充 HTML
+   * @param spinner
+   */
+  function fillHTML(spinner) {
+      var $spinner = $(spinner);
+      var layer = $spinner.hasClass('mdui-spinner-colorful')
+          ? layerHTML(1) + layerHTML(2) + layerHTML(3) + layerHTML(4)
+          : layerHTML();
+      $spinner.html(layer);
+  }
+  $(function () {
+      // 页面加载完后自动填充 HTML 结构
+      mdui.mutation('.mdui-spinner', function () {
+          fillHTML(this);
+      });
+  });
+  mdui.updateSpinners = function (selector) {
+      var $elements = isUndefined(selector) ? $('.mdui-spinner') : $(selector);
+      $elements.each(function () {
+          fillHTML(this);
+      });
+  };
+
+  var DEFAULT_OPTIONS$d = {
+      position: 'auto',
+      align: 'auto',
+      gutter: 16,
+      fixed: false,
+      covered: 'auto',
+      subMenuTrigger: 'hover',
+      subMenuDelay: 200,
+  };
+  var Menu = function Menu(anchorSelector, menuSelector, options) {
+      var this$1 = this;
+      if ( options === void 0 ) options = {};
+
+      /**
+       * 配置参数
+       */
+      this.options = extend({}, DEFAULT_OPTIONS$d);
+      /**
+       * 当前菜单状态
+       */
+      this.state = 'closed';
+      this.$anchor = $(anchorSelector).first();
+      this.$element = $(menuSelector).first();
+      // 触发菜单的元素 和 菜单必须是同级的元素,否则菜单可能不能定位
+      if (!this.$anchor.parent().is(this.$element.parent())) {
+          throw new Error('anchorSelector and menuSelector must be siblings');
+      }
+      extend(this.options, options);
+      // 是否是级联菜单
+      this.isCascade = this.$element.hasClass('mdui-menu-cascade');
+      // covered 参数处理
+      this.isCovered =
+          this.options.covered === 'auto' ? !this.isCascade : this.options.covered;
+      // 点击触发菜单切换
+      this.$anchor.on('click', function () { return this$1.toggle(); });
+      // 点击菜单外面区域关闭菜单
+      $document.on('click touchstart', function (event) {
+          var $target = $(event.target);
+          if (this$1.isOpen() &&
+              !$target.is(this$1.$element) &&
+              !contains(this$1.$element[0], $target[0]) &&
+              !$target.is(this$1.$anchor) &&
+              !contains(this$1.$anchor[0], $target[0])) {
+              this$1.close();
+          }
+      });
+      // 点击不含子菜单的菜单条目关闭菜单
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      var that = this;
+      $document.on('click', '.mdui-menu-item', function () {
+          var $item = $(this);
+          if (!$item.find('.mdui-menu').length &&
+              $item.attr('disabled') === undefined) {
+              that.close();
+          }
+      });
+      // 绑定点击或鼠标移入含子菜单的条目的事件
+      this.bindSubMenuEvent();
+      // 窗口大小变化时,重新调整菜单位置
+      $window.on('resize', $.throttle(function () { return this$1.readjust(); }, 100));
+  };
+  /**
+   * 是否为打开状态
+   */
+  Menu.prototype.isOpen = function isOpen () {
+      return this.state === 'opening' || this.state === 'opened';
+  };
+  /**
+   * 触发组件事件
+   * @param name
+   */
+  Menu.prototype.triggerEvent = function triggerEvent (name) {
+      componentEvent(name, 'menu', this.$element, this);
+  };
+  /**
+   * 调整主菜单位置
+   */
+  Menu.prototype.readjust = function readjust () {
+      var menuLeft;
+      var menuTop;
+      // 菜单位置和方向
+      var position;
+      var align;
+      // window 窗口的宽度和高度
+      var windowHeight = $window.height();
+      var windowWidth = $window.width();
+      // 配置参数
+      var gutter = this.options.gutter;
+      var isCovered = this.isCovered;
+      var isFixed = this.options.fixed;
+      // 动画方向参数
+      var transformOriginX;
+      var transformOriginY;
+      // 菜单的原始宽度和高度
+      var menuWidth = this.$element.width();
+      var menuHeight = this.$element.height();
+      // 触发菜单的元素在窗口中的位置
+      var anchorRect = this.$anchor[0].getBoundingClientRect();
+      var anchorTop = anchorRect.top;
+      var anchorLeft = anchorRect.left;
+      var anchorHeight = anchorRect.height;
+      var anchorWidth = anchorRect.width;
+      var anchorBottom = windowHeight - anchorTop - anchorHeight;
+      var anchorRight = windowWidth - anchorLeft - anchorWidth;
+      // 触发元素相对其拥有定位属性的父元素的位置
+      var anchorOffsetTop = this.$anchor[0].offsetTop;
+      var anchorOffsetLeft = this.$anchor[0].offsetLeft;
+      // 自动判断菜单位置
+      if (this.options.position === 'auto') {
+          if (anchorBottom + (isCovered ? anchorHeight : 0) > menuHeight + gutter) {
+              // 判断下方是否放得下菜单
+              position = 'bottom';
+          }
+          else if (anchorTop + (isCovered ? anchorHeight : 0) >
+              menuHeight + gutter) {
+              // 判断上方是否放得下菜单
+              position = 'top';
+          }
+          else {
+              // 上下都放不下,居中显示
+              position = 'center';
+          }
+      }
+      else {
+          position = this.options.position;
+      }
+      // 自动判断菜单对齐方式
+      if (this.options.align === 'auto') {
+          if (anchorRight + anchorWidth > menuWidth + gutter) {
+              // 判断右侧是否放得下菜单
+              align = 'left';
+          }
+          else if (anchorLeft + anchorWidth > menuWidth + gutter) {
+              // 判断左侧是否放得下菜单
+              align = 'right';
+          }
+          else {
+              // 左右都放不下,居中显示
+              align = 'center';
+          }
+      }
+      else {
+          align = this.options.align;
+      }
+      // 设置菜单位置
+      if (position === 'bottom') {
+          transformOriginY = '0';
+          menuTop =
+              (isCovered ? 0 : anchorHeight) +
+                  (isFixed ? anchorTop : anchorOffsetTop);
+      }
+      else if (position === 'top') {
+          transformOriginY = '100%';
+          menuTop =
+              (isCovered ? anchorHeight : 0) +
+                  (isFixed ? anchorTop - menuHeight : anchorOffsetTop - menuHeight);
+      }
+      else {
+          transformOriginY = '50%';
+          // =====================在窗口中居中
+          // 显示的菜单的高度,简单菜单高度不超过窗口高度,若超过了则在菜单内部显示滚动条
+          // 级联菜单内部不允许出现滚动条
+          var menuHeightTemp = menuHeight;
+          // 简单菜单比窗口高时,限制菜单高度
+          if (!this.isCascade) {
+              if (menuHeight + gutter * 2 > windowHeight) {
+                  menuHeightTemp = windowHeight - gutter * 2;
+                  this.$element.height(menuHeightTemp);
+              }
+          }
+          menuTop =
+              (windowHeight - menuHeightTemp) / 2 +
+                  (isFixed ? 0 : anchorOffsetTop - anchorTop);
+      }
+      this.$element.css('top', (menuTop + "px"));
+      // 设置菜单对齐方式
+      if (align === 'left') {
+          transformOriginX = '0';
+          menuLeft = isFixed ? anchorLeft : anchorOffsetLeft;
+      }
+      else if (align === 'right') {
+          transformOriginX = '100%';
+          menuLeft = isFixed
+              ? anchorLeft + anchorWidth - menuWidth
+              : anchorOffsetLeft + anchorWidth - menuWidth;
+      }
+      else {
+          transformOriginX = '50%';
+          //=======================在窗口中居中
+          // 显示的菜单的宽度,菜单宽度不能超过窗口宽度
+          var menuWidthTemp = menuWidth;
+          // 菜单比窗口宽,限制菜单宽度
+          if (menuWidth + gutter * 2 > windowWidth) {
+              menuWidthTemp = windowWidth - gutter * 2;
+              this.$element.width(menuWidthTemp);
+          }
+          menuLeft =
+              (windowWidth - menuWidthTemp) / 2 +
+                  (isFixed ? 0 : anchorOffsetLeft - anchorLeft);
+      }
+      this.$element.css('left', (menuLeft + "px"));
+      // 设置菜单动画方向
+      this.$element.transformOrigin((transformOriginX + " " + transformOriginY));
+  };
+  /**
+   * 调整子菜单的位置
+   * @param $submenu
+   */
+  Menu.prototype.readjustSubmenu = function readjustSubmenu ($submenu) {
+      var $item = $submenu.parent('.mdui-menu-item');
+      var submenuTop;
+      var submenuLeft;
+      // 子菜单位置和方向
+      var position;
+      var align;
+      // window 窗口的宽度和高度
+      var windowHeight = $window.height();
+      var windowWidth = $window.width();
+      // 动画方向参数
+      var transformOriginX;
+      var transformOriginY;
+      // 子菜单的原始宽度和高度
+      var submenuWidth = $submenu.width();
+      var submenuHeight = $submenu.height();
+      // 触发子菜单的菜单项的宽度高度
+      var itemRect = $item[0].getBoundingClientRect();
+      var itemWidth = itemRect.width;
+      var itemHeight = itemRect.height;
+      var itemLeft = itemRect.left;
+      var itemTop = itemRect.top;
+      // 判断菜单上下位置
+      if (windowHeight - itemTop > submenuHeight) {
+          // 判断下方是否放得下菜单
+          position = 'bottom';
+      }
+      else if (itemTop + itemHeight > submenuHeight) {
+          // 判断上方是否放得下菜单
+          position = 'top';
+      }
+      else {
+          // 默认放在下方
+          position = 'bottom';
+      }
+      // 判断菜单左右位置
+      if (windowWidth - itemLeft - itemWidth > submenuWidth) {
+          // 判断右侧是否放得下菜单
+          align = 'left';
+      }
+      else if (itemLeft > submenuWidth) {
+          // 判断左侧是否放得下菜单
+          align = 'right';
+      }
+      else {
+          // 默认放在右侧
+          align = 'left';
+      }
+      // 设置菜单位置
+      if (position === 'bottom') {
+          transformOriginY = '0';
+          submenuTop = '0';
+      }
+      else if (position === 'top') {
+          transformOriginY = '100%';
+          submenuTop = -submenuHeight + itemHeight;
+      }
+      $submenu.css('top', (submenuTop + "px"));
+      // 设置菜单对齐方式
+      if (align === 'left') {
+          transformOriginX = '0';
+          submenuLeft = itemWidth;
+      }
+      else if (align === 'right') {
+          transformOriginX = '100%';
+          submenuLeft = -submenuWidth;
+      }
+      $submenu.css('left', (submenuLeft + "px"));
+      // 设置菜单动画方向
+      $submenu.transformOrigin((transformOriginX + " " + transformOriginY));
+  };
+  /**
+   * 打开子菜单
+   * @param $submenu
+   */
+  Menu.prototype.openSubMenu = function openSubMenu ($submenu) {
+      this.readjustSubmenu($submenu);
+      $submenu
+          .addClass('mdui-menu-open')
+          .parent('.mdui-menu-item')
+          .addClass('mdui-menu-item-active');
+  };
+  /**
+   * 关闭子菜单,及其嵌套的子菜单
+   * @param $submenu
+   */
+  Menu.prototype.closeSubMenu = function closeSubMenu ($submenu) {
+      // 关闭子菜单
+      $submenu
+          .removeClass('mdui-menu-open')
+          .addClass('mdui-menu-closing')
+          .transitionEnd(function () { return $submenu.removeClass('mdui-menu-closing'); })
+          // 移除激活状态的样式
+          .parent('.mdui-menu-item')
+          .removeClass('mdui-menu-item-active');
+      // 循环关闭嵌套的子菜单
+      $submenu.find('.mdui-menu').each(function (_, menu) {
+          var $subSubmenu = $(menu);
+          $subSubmenu
+              .removeClass('mdui-menu-open')
+              .addClass('mdui-menu-closing')
+              .transitionEnd(function () { return $subSubmenu.removeClass('mdui-menu-closing'); })
+              .parent('.mdui-menu-item')
+              .removeClass('mdui-menu-item-active');
+      });
+  };
+  /**
+   * 切换子菜单状态
+   * @param $submenu
+   */
+  Menu.prototype.toggleSubMenu = function toggleSubMenu ($submenu) {
+      $submenu.hasClass('mdui-menu-open')
+          ? this.closeSubMenu($submenu)
+          : this.openSubMenu($submenu);
+  };
+  /**
+   * 绑定子菜单事件
+   */
+  Menu.prototype.bindSubMenuEvent = function bindSubMenuEvent () {
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      var that = this;
+      // 点击打开子菜单
+      this.$element.on('click', '.mdui-menu-item', function (event) {
+          var $item = $(this);
+          var $target = $(event.target);
+          // 禁用状态菜单不操作
+          if ($item.attr('disabled') !== undefined) {
+              return;
+          }
+          // 没有点击在子菜单的菜单项上时,不操作(点在了子菜单的空白区域、或分隔线上)
+          if ($target.is('.mdui-menu') || $target.is('.mdui-divider')) {
+              return;
+          }
+          // 阻止冒泡,点击菜单项时只在最后一级的 mdui-menu-item 上生效,不向上冒泡
+          if (!$target.parents('.mdui-menu-item').first().is($item)) {
+              return;
+          }
+          // 当前菜单的子菜单
+          var $submenu = $item.children('.mdui-menu');
+          // 先关闭除当前子菜单外的所有同级子菜单
+          $item
+              .parent('.mdui-menu')
+              .children('.mdui-menu-item')
+              .each(function (_, item) {
+              var $tmpSubmenu = $(item).children('.mdui-menu');
+              if ($tmpSubmenu.length &&
+                  (!$submenu.length || !$tmpSubmenu.is($submenu))) {
+                  that.closeSubMenu($tmpSubmenu);
+              }
+          });
+          // 切换当前子菜单
+          if ($submenu.length) {
+              that.toggleSubMenu($submenu);
+          }
+      });
+      if (this.options.subMenuTrigger === 'hover') {
+          // 临时存储 setTimeout 对象
+          var timeout = null;
+          var timeoutOpen = null;
+          this.$element.on('mouseover mouseout', '.mdui-menu-item', function (event) {
+              var $item = $(this);
+              var eventType = event.type;
+              var $relatedTarget = $(event.relatedTarget);
+              // 禁用状态的菜单不操作
+              if ($item.attr('disabled') !== undefined) {
+                  return;
+              }
+              // 用 mouseover 模拟 mouseenter
+              if (eventType === 'mouseover') {
+                  if (!$item.is($relatedTarget) &&
+                      contains($item[0], $relatedTarget[0])) {
+                      return;
+                  }
+              }
+              // 用 mouseout 模拟 mouseleave
+              else if (eventType === 'mouseout') {
+                  if ($item.is($relatedTarget) ||
+                      contains($item[0], $relatedTarget[0])) {
+                      return;
+                  }
+              }
+              // 当前菜单项下的子菜单,未必存在
+              var $submenu = $item.children('.mdui-menu');
+              // 鼠标移入菜单项时,显示菜单项下的子菜单
+              if (eventType === 'mouseover') {
+                  if ($submenu.length) {
+                      // 当前子菜单准备打开时,如果当前子菜单正准备着关闭,不用再关闭了
+                      var tmpClose = $submenu.data('timeoutClose.mdui.menu');
+                      if (tmpClose) {
+                          clearTimeout(tmpClose);
+                      }
+                      // 如果当前子菜单已经打开,不操作
+                      if ($submenu.hasClass('mdui-menu-open')) {
+                          return;
+                      }
+                      // 当前子菜单准备打开时,其他准备打开的子菜单不用再打开了
+                      clearTimeout(timeoutOpen);
+                      // 准备打开当前子菜单
+                      timeout = timeoutOpen = setTimeout(function () { return that.openSubMenu($submenu); }, that.options.subMenuDelay);
+                      $submenu.data('timeoutOpen.mdui.menu', timeout);
+                  }
+              }
+              // 鼠标移出菜单项时,关闭菜单项下的子菜单
+              else if (eventType === 'mouseout') {
+                  if ($submenu.length) {
+                      // 鼠标移出菜单项时,如果当前菜单项下的子菜单正准备打开,不用再打开了
+                      var tmpOpen = $submenu.data('timeoutOpen.mdui.menu');
+                      if (tmpOpen) {
+                          clearTimeout(tmpOpen);
+                      }
+                      // 准备关闭当前子菜单
+                      timeout = setTimeout(function () { return that.closeSubMenu($submenu); }, that.options.subMenuDelay);
+                      $submenu.data('timeoutClose.mdui.menu', timeout);
+                  }
+              }
+          });
+      }
+  };
+  /**
+   * 动画结束回调
+   */
+  Menu.prototype.transitionEnd = function transitionEnd () {
+      this.$element.removeClass('mdui-menu-closing');
+      if (this.state === 'opening') {
+          this.state = 'opened';
+          this.triggerEvent('opened');
+      }
+      if (this.state === 'closing') {
+          this.state = 'closed';
+          this.triggerEvent('closed');
+          // 关闭后,恢复菜单样式到默认状态,并恢复 fixed 定位
+          this.$element.css({
+              top: '',
+              left: '',
+              width: '',
+              position: 'fixed',
+          });
+      }
+  };
+  /**
+   * 切换菜单状态
+   */
+  Menu.prototype.toggle = function toggle () {
+      this.isOpen() ? this.close() : this.open();
+  };
+  /**
+   * 打开菜单
+   */
+  Menu.prototype.open = function open () {
+          var this$1 = this;
+
+      if (this.isOpen()) {
+          return;
+      }
+      this.state = 'opening';
+      this.triggerEvent('open');
+      this.readjust();
+      this.$element
+          // 菜单隐藏状态使用使用 fixed 定位。
+          .css('position', this.options.fixed ? 'fixed' : 'absolute')
+          .addClass('mdui-menu-open')
+          .transitionEnd(function () { return this$1.transitionEnd(); });
+  };
+  /**
+   * 关闭菜单
+   */
+  Menu.prototype.close = function close () {
+          var this$1 = this;
+
+      if (!this.isOpen()) {
+          return;
+      }
+      this.state = 'closing';
+      this.triggerEvent('close');
+      // 菜单开始关闭时,关闭所有子菜单
+      this.$element.find('.mdui-menu').each(function (_, submenu) {
+          this$1.closeSubMenu($(submenu));
+      });
+      this.$element
+          .removeClass('mdui-menu-open')
+          .addClass('mdui-menu-closing')
+          .transitionEnd(function () { return this$1.transitionEnd(); });
+  };
+  mdui.Menu = Menu;
+
+  var customAttr$9 = 'mdui-menu';
+  var dataName$3 = '_mdui_menu';
+  $(function () {
+      $document.on('click', ("[" + customAttr$9 + "]"), function () {
+          var $this = $(this);
+          var instance = $this.data(dataName$3);
+          if (!instance) {
+              var options = parseOptions(this, customAttr$9);
+              var menuSelector = options.target;
+              // @ts-ignore
+              delete options.target;
+              instance = new mdui.Menu($this, menuSelector, options);
+              $this.data(dataName$3, instance);
+              instance.toggle();
+          }
+      });
+  });
+
+  return mdui;
+
+})));
+//# sourceMappingURL=mdui.js.map

File diff suppressed because it is too large
+ 0 - 0
koyeb/web/js/mdui.js.map


File diff suppressed because it is too large
+ 5 - 0
koyeb/web/js/mdui.min.js


File diff suppressed because it is too large
+ 0 - 0
koyeb/web/js/mdui.min.js.map


+ 7 - 0
koyeb/web/vendor/autoload.php

@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInit4878b46070bce6badfc3eed82958f8ec::getLoader();

+ 572 - 0
koyeb/web/vendor/composer/ClassLoader.php

@@ -0,0 +1,572 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <[email protected]>
+ *     Jordi Boggiano <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ *     $loader = new \Composer\Autoload\ClassLoader();
+ *
+ *     // register classes with namespaces
+ *     $loader->add('Symfony\Component', __DIR__.'/component');
+ *     $loader->add('Symfony',           __DIR__.'/framework');
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ *     // to enable searching the include path (eg. for PEAR packages)
+ *     $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <[email protected]>
+ * @author Jordi Boggiano <[email protected]>
+ * @see    https://www.php-fig.org/psr/psr-0/
+ * @see    https://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+    /** @var ?string */
+    private $vendorDir;
+
+    // PSR-4
+    /**
+     * @var array[]
+     * @psalm-var array<string, array<string, int>>
+     */
+    private $prefixLengthsPsr4 = array();
+    /**
+     * @var array[]
+     * @psalm-var array<string, array<int, string>>
+     */
+    private $prefixDirsPsr4 = array();
+    /**
+     * @var array[]
+     * @psalm-var array<string, string>
+     */
+    private $fallbackDirsPsr4 = array();
+
+    // PSR-0
+    /**
+     * @var array[]
+     * @psalm-var array<string, array<string, string[]>>
+     */
+    private $prefixesPsr0 = array();
+    /**
+     * @var array[]
+     * @psalm-var array<string, string>
+     */
+    private $fallbackDirsPsr0 = array();
+
+    /** @var bool */
+    private $useIncludePath = false;
+
+    /**
+     * @var string[]
+     * @psalm-var array<string, string>
+     */
+    private $classMap = array();
+
+    /** @var bool */
+    private $classMapAuthoritative = false;
+
+    /**
+     * @var bool[]
+     * @psalm-var array<string, bool>
+     */
+    private $missingClasses = array();
+
+    /** @var ?string */
+    private $apcuPrefix;
+
+    /**
+     * @var self[]
+     */
+    private static $registeredLoaders = array();
+
+    /**
+     * @param ?string $vendorDir
+     */
+    public function __construct($vendorDir = null)
+    {
+        $this->vendorDir = $vendorDir;
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getPrefixes()
+    {
+        if (!empty($this->prefixesPsr0)) {
+            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
+        }
+
+        return array();
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return array<string, array<int, string>>
+     */
+    public function getPrefixesPsr4()
+    {
+        return $this->prefixDirsPsr4;
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return array<string, string>
+     */
+    public function getFallbackDirs()
+    {
+        return $this->fallbackDirsPsr0;
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return array<string, string>
+     */
+    public function getFallbackDirsPsr4()
+    {
+        return $this->fallbackDirsPsr4;
+    }
+
+    /**
+     * @return string[] Array of classname => path
+     * @psalm-var array<string, string>
+     */
+    public function getClassMap()
+    {
+        return $this->classMap;
+    }
+
+    /**
+     * @param string[] $classMap Class to filename map
+     * @psalm-param array<string, string> $classMap
+     *
+     * @return void
+     */
+    public function addClassMap(array $classMap)
+    {
+        if ($this->classMap) {
+            $this->classMap = array_merge($this->classMap, $classMap);
+        } else {
+            $this->classMap = $classMap;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix, either
+     * appending or prepending to the ones previously set for this prefix.
+     *
+     * @param string          $prefix  The prefix
+     * @param string[]|string $paths   The PSR-0 root directories
+     * @param bool            $prepend Whether to prepend the directories
+     *
+     * @return void
+     */
+    public function add($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            if ($prepend) {
+                $this->fallbackDirsPsr0 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr0
+                );
+            } else {
+                $this->fallbackDirsPsr0 = array_merge(
+                    $this->fallbackDirsPsr0,
+                    (array) $paths
+                );
+            }
+
+            return;
+        }
+
+        $first = $prefix[0];
+        if (!isset($this->prefixesPsr0[$first][$prefix])) {
+            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+            return;
+        }
+        if ($prepend) {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixesPsr0[$first][$prefix]
+            );
+        } else {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                $this->prefixesPsr0[$first][$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace, either
+     * appending or prepending to the ones previously set for this namespace.
+     *
+     * @param string          $prefix  The prefix/namespace, with trailing '\\'
+     * @param string[]|string $paths   The PSR-4 base directories
+     * @param bool            $prepend Whether to prepend the directories
+     *
+     * @throws \InvalidArgumentException
+     *
+     * @return void
+     */
+    public function addPsr4($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            // Register directories for the root namespace.
+            if ($prepend) {
+                $this->fallbackDirsPsr4 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr4
+                );
+            } else {
+                $this->fallbackDirsPsr4 = array_merge(
+                    $this->fallbackDirsPsr4,
+                    (array) $paths
+                );
+            }
+        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+            // Register directories for a new namespace.
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        } elseif ($prepend) {
+            // Prepend directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixDirsPsr4[$prefix]
+            );
+        } else {
+            // Append directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                $this->prefixDirsPsr4[$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix,
+     * replacing any others previously set for this prefix.
+     *
+     * @param string          $prefix The prefix
+     * @param string[]|string $paths  The PSR-0 base directories
+     *
+     * @return void
+     */
+    public function set($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr0 = (array) $paths;
+        } else {
+            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace,
+     * replacing any others previously set for this namespace.
+     *
+     * @param string          $prefix The prefix/namespace, with trailing '\\'
+     * @param string[]|string $paths  The PSR-4 base directories
+     *
+     * @throws \InvalidArgumentException
+     *
+     * @return void
+     */
+    public function setPsr4($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr4 = (array) $paths;
+        } else {
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Turns on searching the include path for class files.
+     *
+     * @param bool $useIncludePath
+     *
+     * @return void
+     */
+    public function setUseIncludePath($useIncludePath)
+    {
+        $this->useIncludePath = $useIncludePath;
+    }
+
+    /**
+     * Can be used to check if the autoloader uses the include path to check
+     * for classes.
+     *
+     * @return bool
+     */
+    public function getUseIncludePath()
+    {
+        return $this->useIncludePath;
+    }
+
+    /**
+     * Turns off searching the prefix and fallback directories for classes
+     * that have not been registered with the class map.
+     *
+     * @param bool $classMapAuthoritative
+     *
+     * @return void
+     */
+    public function setClassMapAuthoritative($classMapAuthoritative)
+    {
+        $this->classMapAuthoritative = $classMapAuthoritative;
+    }
+
+    /**
+     * Should class lookup fail if not found in the current class map?
+     *
+     * @return bool
+     */
+    public function isClassMapAuthoritative()
+    {
+        return $this->classMapAuthoritative;
+    }
+
+    /**
+     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+     *
+     * @param string|null $apcuPrefix
+     *
+     * @return void
+     */
+    public function setApcuPrefix($apcuPrefix)
+    {
+        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
+    }
+
+    /**
+     * The APCu prefix in use, or null if APCu caching is not enabled.
+     *
+     * @return string|null
+     */
+    public function getApcuPrefix()
+    {
+        return $this->apcuPrefix;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not
+     *
+     * @return void
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+
+        if (null === $this->vendorDir) {
+            return;
+        }
+
+        if ($prepend) {
+            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
+        } else {
+            unset(self::$registeredLoaders[$this->vendorDir]);
+            self::$registeredLoaders[$this->vendorDir] = $this;
+        }
+    }
+
+    /**
+     * Unregisters this instance as an autoloader.
+     *
+     * @return void
+     */
+    public function unregister()
+    {
+        spl_autoload_unregister(array($this, 'loadClass'));
+
+        if (null !== $this->vendorDir) {
+            unset(self::$registeredLoaders[$this->vendorDir]);
+        }
+    }
+
+    /**
+     * Loads the given class or interface.
+     *
+     * @param  string    $class The name of the class
+     * @return true|null True if loaded, null otherwise
+     */
+    public function loadClass($class)
+    {
+        if ($file = $this->findFile($class)) {
+            includeFile($file);
+
+            return true;
+        }
+
+        return null;
+    }
+
+    /**
+     * Finds the path to the file where the class is defined.
+     *
+     * @param string $class The name of the class
+     *
+     * @return string|false The path if found, false otherwise
+     */
+    public function findFile($class)
+    {
+        // class map lookup
+        if (isset($this->classMap[$class])) {
+            return $this->classMap[$class];
+        }
+        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+            return false;
+        }
+        if (null !== $this->apcuPrefix) {
+            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+            if ($hit) {
+                return $file;
+            }
+        }
+
+        $file = $this->findFileWithExtension($class, '.php');
+
+        // Search for Hack files if we are running on HHVM
+        if (false === $file && defined('HHVM_VERSION')) {
+            $file = $this->findFileWithExtension($class, '.hh');
+        }
+
+        if (null !== $this->apcuPrefix) {
+            apcu_add($this->apcuPrefix.$class, $file);
+        }
+
+        if (false === $file) {
+            // Remember that this class does not exist.
+            $this->missingClasses[$class] = true;
+        }
+
+        return $file;
+    }
+
+    /**
+     * Returns the currently registered loaders indexed by their corresponding vendor directories.
+     *
+     * @return self[]
+     */
+    public static function getRegisteredLoaders()
+    {
+        return self::$registeredLoaders;
+    }
+
+    /**
+     * @param  string       $class
+     * @param  string       $ext
+     * @return string|false
+     */
+    private function findFileWithExtension($class, $ext)
+    {
+        // PSR-4 lookup
+        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+        $first = $class[0];
+        if (isset($this->prefixLengthsPsr4[$first])) {
+            $subPath = $class;
+            while (false !== $lastPos = strrpos($subPath, '\\')) {
+                $subPath = substr($subPath, 0, $lastPos);
+                $search = $subPath . '\\';
+                if (isset($this->prefixDirsPsr4[$search])) {
+                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
+                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
+                        if (file_exists($file = $dir . $pathEnd)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-4 fallback dirs
+        foreach ($this->fallbackDirsPsr4 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 lookup
+        if (false !== $pos = strrpos($class, '\\')) {
+            // namespaced class name
+            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+        } else {
+            // PEAR-like class name
+            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+        }
+
+        if (isset($this->prefixesPsr0[$first])) {
+            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($dirs as $dir) {
+                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-0 fallback dirs
+        foreach ($this->fallbackDirsPsr0 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 include paths.
+        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+            return $file;
+        }
+
+        return false;
+    }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param  string $file
+ * @return void
+ * @private
+ */
+function includeFile($file)
+{
+    include $file;
+}

+ 337 - 0
koyeb/web/vendor/composer/InstalledVersions.php

@@ -0,0 +1,337 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <[email protected]>
+ *     Jordi Boggiano <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer;
+
+use Composer\Autoload\ClassLoader;
+use Composer\Semver\VersionParser;
+
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require its presence, you can require `composer-runtime-api ^2.0`
+ */
+class InstalledVersions
+{
+    private static $installed;
+    private static $canGetVendors;
+    private static $installedByVendor = array();
+
+    /**
+     * Returns a list of all package names which are present, either by being installed, replaced or provided
+     *
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackages()
+    {
+        $packages = array();
+        foreach (self::getInstalled() as $installed) {
+            $packages[] = array_keys($installed['versions']);
+        }
+
+        if (1 === \count($packages)) {
+            return $packages[0];
+        }
+
+        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+    }
+
+    /**
+     * Returns a list of all package names with a specific type e.g. 'library'
+     *
+     * @param  string   $type
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackagesByType($type)
+    {
+        $packagesByType = array();
+
+        foreach (self::getInstalled() as $installed) {
+            foreach ($installed['versions'] as $name => $package) {
+                if (isset($package['type']) && $package['type'] === $type) {
+                    $packagesByType[] = $name;
+                }
+            }
+        }
+
+        return $packagesByType;
+    }
+
+    /**
+     * Checks whether the given package is installed
+     *
+     * This also returns true if the package name is provided or replaced by another package
+     *
+     * @param  string $packageName
+     * @param  bool   $includeDevRequirements
+     * @return bool
+     */
+    public static function isInstalled($packageName, $includeDevRequirements = true)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (isset($installed['versions'][$packageName])) {
+                return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks whether the given package satisfies a version constraint
+     *
+     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+     *
+     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+     *
+     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
+     * @param  string        $packageName
+     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+     * @return bool
+     */
+    public static function satisfies(VersionParser $parser, $packageName, $constraint)
+    {
+        $constraint = $parser->parseConstraints($constraint);
+        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+        return $provided->matches($constraint);
+    }
+
+    /**
+     * Returns a version constraint representing all the range(s) which are installed for a given package
+     *
+     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+     * whether a given version of a package is installed, and not just whether it exists
+     *
+     * @param  string $packageName
+     * @return string Version constraint usable with composer/semver
+     */
+    public static function getVersionRanges($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            $ranges = array();
+            if (isset($installed['versions'][$packageName]['pretty_version'])) {
+                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+            }
+            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+            }
+            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+            }
+            if (array_key_exists('provided', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+            }
+
+            return implode(' || ', $ranges);
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getPrettyVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['pretty_version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+     */
+    public static function getReference($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['reference'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['reference'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+     */
+    public static function getInstallPath($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @return array
+     * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
+     */
+    public static function getRootPackage()
+    {
+        $installed = self::getInstalled();
+
+        return $installed[0]['root'];
+    }
+
+    /**
+     * Returns the raw installed.php data for custom implementations
+     *
+     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+     * @return array[]
+     * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
+     */
+    public static function getRawData()
+    {
+        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                self::$installed = include __DIR__ . '/installed.php';
+            } else {
+                self::$installed = array();
+            }
+        }
+
+        return self::$installed;
+    }
+
+    /**
+     * Returns the raw data of all installed.php which are currently loaded for custom implementations
+     *
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+     */
+    public static function getAllRawData()
+    {
+        return self::getInstalled();
+    }
+
+    /**
+     * Lets you reload the static array from another file
+     *
+     * This is only useful for complex integrations in which a project needs to use
+     * this class but then also needs to execute another project's autoloader in process,
+     * and wants to ensure both projects have access to their version of installed.php.
+     *
+     * A typical case would be PHPUnit, where it would need to make sure it reads all
+     * the data it needs from this class, then call reload() with
+     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+     * the project in which it runs can then also use this class safely, without
+     * interference between PHPUnit's dependencies and the project's dependencies.
+     *
+     * @param  array[] $data A vendor/composer/installed.php data set
+     * @return void
+     *
+     * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
+     */
+    public static function reload($data)
+    {
+        self::$installed = $data;
+        self::$installedByVendor = array();
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+     */
+    private static function getInstalled()
+    {
+        if (null === self::$canGetVendors) {
+            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+        }
+
+        $installed = array();
+
+        if (self::$canGetVendors) {
+            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+                if (isset(self::$installedByVendor[$vendorDir])) {
+                    $installed[] = self::$installedByVendor[$vendorDir];
+                } elseif (is_file($vendorDir.'/composer/installed.php')) {
+                    $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
+                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
+                        self::$installed = $installed[count($installed) - 1];
+                    }
+                }
+            }
+        }
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                self::$installed = require __DIR__ . '/installed.php';
+            } else {
+                self::$installed = array();
+            }
+        }
+        $installed[] = self::$installed;
+
+        return $installed;
+    }
+}

+ 21 - 0
koyeb/web/vendor/composer/LICENSE

@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+

+ 10 - 0
koyeb/web/vendor/composer/autoload_classmap.php

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
+);

+ 9 - 0
koyeb/web/vendor/composer/autoload_namespaces.php

@@ -0,0 +1,9 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+);

+ 10 - 0
koyeb/web/vendor/composer/autoload_psr4.php

@@ -0,0 +1,10 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'SensioLabs\\AnsiConverter\\' => array($vendorDir . '/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter'),
+);

+ 57 - 0
koyeb/web/vendor/composer/autoload_real.php

@@ -0,0 +1,57 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit4878b46070bce6badfc3eed82958f8ec
+{
+    private static $loader;
+
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
+    /**
+     * @return \Composer\Autoload\ClassLoader
+     */
+    public static function getLoader()
+    {
+        if (null !== self::$loader) {
+            return self::$loader;
+        }
+
+        require __DIR__ . '/platform_check.php';
+
+        spl_autoload_register(array('ComposerAutoloaderInit4878b46070bce6badfc3eed82958f8ec', 'loadClassLoader'), true, true);
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
+        spl_autoload_unregister(array('ComposerAutoloaderInit4878b46070bce6badfc3eed82958f8ec', 'loadClassLoader'));
+
+        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+        if ($useStaticLoader) {
+            require __DIR__ . '/autoload_static.php';
+
+            call_user_func(\Composer\Autoload\ComposerStaticInit4878b46070bce6badfc3eed82958f8ec::getInitializer($loader));
+        } else {
+            $map = require __DIR__ . '/autoload_namespaces.php';
+            foreach ($map as $namespace => $path) {
+                $loader->set($namespace, $path);
+            }
+
+            $map = require __DIR__ . '/autoload_psr4.php';
+            foreach ($map as $namespace => $path) {
+                $loader->setPsr4($namespace, $path);
+            }
+
+            $classMap = require __DIR__ . '/autoload_classmap.php';
+            if ($classMap) {
+                $loader->addClassMap($classMap);
+            }
+        }
+
+        $loader->register(true);
+
+        return $loader;
+    }
+}

+ 36 - 0
koyeb/web/vendor/composer/autoload_static.php

@@ -0,0 +1,36 @@
+<?php
+
+// autoload_static.php @generated by Composer
+
+namespace Composer\Autoload;
+
+class ComposerStaticInit4878b46070bce6badfc3eed82958f8ec
+{
+    public static $prefixLengthsPsr4 = array (
+        'S' => 
+        array (
+            'SensioLabs\\AnsiConverter\\' => 25,
+        ),
+    );
+
+    public static $prefixDirsPsr4 = array (
+        'SensioLabs\\AnsiConverter\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter',
+        ),
+    );
+
+    public static $classMap = array (
+        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
+    );
+
+    public static function getInitializer(ClassLoader $loader)
+    {
+        return \Closure::bind(function () use ($loader) {
+            $loader->prefixLengthsPsr4 = ComposerStaticInit4878b46070bce6badfc3eed82958f8ec::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInit4878b46070bce6badfc3eed82958f8ec::$prefixDirsPsr4;
+            $loader->classMap = ComposerStaticInit4878b46070bce6badfc3eed82958f8ec::$classMap;
+
+        }, null, ClassLoader::class);
+    }
+}

+ 69 - 0
koyeb/web/vendor/composer/installed.json

@@ -0,0 +1,69 @@
+{
+    "packages": [
+        {
+            "name": "sensiolabs/ansi-to-html",
+            "version": "v1.2.1",
+            "version_normalized": "1.2.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sensiolabs/ansi-to-html.git",
+                "reference": "94a3145aae4733ff933c8910263ef56d1ae317a9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sensiolabs/ansi-to-html/zipball/94a3145aae4733ff933c8910263ef56d1ae317a9",
+                "reference": "94a3145aae4733ff933c8910263ef56d1ae317a9",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.2.5"
+            },
+            "conflict": {
+                "twig/twig": "< 2.4.0"
+            },
+            "require-dev": {
+                "twig/twig": "^2.4 || ^3.0"
+            },
+            "suggest": {
+                "twig/twig": "Provides nice templating features"
+            },
+            "time": "2020-10-06T05:48:55+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.2-dev"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "SensioLabs\\AnsiConverter\\": "SensioLabs/AnsiConverter"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "[email protected]"
+                }
+            ],
+            "description": "A library to convert a text with ANSI codes to HTML",
+            "support": {
+                "issues": "https://github.com/sensiolabs/ansi-to-html/issues",
+                "source": "https://github.com/sensiolabs/ansi-to-html/tree/v1.2.1"
+            },
+            "install-path": "../sensiolabs/ansi-to-html"
+        }
+    ],
+    "dev": true,
+    "dev-package-names": []
+}

+ 32 - 0
koyeb/web/vendor/composer/installed.php

@@ -0,0 +1,32 @@
+<?php return array(
+    'root' => array(
+        'pretty_version' => 'dev-main',
+        'version' => 'dev-main',
+        'type' => 'library',
+        'install_path' => __DIR__ . '/../../',
+        'aliases' => array(),
+        'reference' => '4a6e1901ee0d1bab8b03b40b04c611219d89dd5e',
+        'name' => '__root__',
+        'dev' => true,
+    ),
+    'versions' => array(
+        '__root__' => array(
+            'pretty_version' => 'dev-main',
+            'version' => 'dev-main',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../../',
+            'aliases' => array(),
+            'reference' => '4a6e1901ee0d1bab8b03b40b04c611219d89dd5e',
+            'dev_requirement' => false,
+        ),
+        'sensiolabs/ansi-to-html' => array(
+            'pretty_version' => 'v1.2.1',
+            'version' => '1.2.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../sensiolabs/ansi-to-html',
+            'aliases' => array(),
+            'reference' => '94a3145aae4733ff933c8910263ef56d1ae317a9',
+            'dev_requirement' => false,
+        ),
+    ),
+);

+ 26 - 0
koyeb/web/vendor/composer/platform_check.php

@@ -0,0 +1,26 @@
+<?php
+
+// platform_check.php @generated by Composer
+
+$issues = array();
+
+if (!(PHP_VERSION_ID >= 70205)) {
+    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.';
+}
+
+if ($issues) {
+    if (!headers_sent()) {
+        header('HTTP/1.1 500 Internal Server Error');
+    }
+    if (!ini_get('display_errors')) {
+        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
+        } elseif (!headers_sent()) {
+            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
+        }
+    }
+    trigger_error(
+        'Composer detected issues in your platform: ' . implode(' ', $issues),
+        E_USER_ERROR
+    );
+}

+ 2 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/.gitignore

@@ -0,0 +1,2 @@
+composer.lock
+/vendor/

+ 19 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2013 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 109 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/README.md

@@ -0,0 +1,109 @@
+ANSI to HTML5 Converter
+=======================
+
+This small library only does one thing: converting a text containing ANSI
+codes to an HTML5 fragment:
+
+```php
+require_once __DIR__.'/vendor/autoload.php';
+
+use SensioLabs\AnsiConverter\AnsiToHtmlConverter;
+
+$converter = new AnsiToHtmlConverter();
+
+$html = $converter->convert($ansi);
+```
+
+The `$ansi` variable should contain a text with ANSI codes, and `$html` will
+contain the converted HTML5 version of it.
+
+You can then output the HTML5 fragment in any HTML document:
+
+```html+php
+<html>
+    <body>
+        <pre style="background-color: black; overflow: auto; padding: 10px 15px; font-family: monospace;"
+        ><?php echo $html ?></pre>
+    </body>
+</html>
+```
+
+The converter supports different color themes:
+
+```php
+use SensioLabs\AnsiConverter\Theme\SolarizedTheme;
+
+$theme = new SolarizedTheme();
+$converter = new AnsiToHtmlConverter($theme);
+```
+
+By default, the colors are inlined into the HTML, but you can also use classes
+by turning off style inlining:
+
+```php
+$converter = new AnsiToHtmlConverter($theme, false);
+```
+
+And the `asCss()` method of the theme object lets you retrieve the theme styles
+as a CSS snippet:
+
+```php
+$styles = $theme->asCss();
+```
+
+which you can then use in your HTML document:
+
+```html+php
+<html>
+    <head>
+        <style>
+            <?php echo $styles ?>
+
+            .ansi_box { overflow: auto; padding: 10px 15px; font-family: monospace; }
+        </style>
+    </head>
+    <body>
+        <pre class="ansi_color_bg_black ansi_color_fg_white ansi_box"><?php echo $html ?></pre>
+    </body>
+</html>
+```
+
+Twig Integration
+----------------
+
+Register the extension:
+
+```php
+use SensioLabs\AnsiConverter\Bridge\Twig\AnsiExtension;
+
+$twig->addExtension(AnsiExtension());
+```
+
+It's possible to use a custom ``AnsiToHtmlConverter``:
+
+```php
+use SensioLabs\AnsiConverter\Bridge\Twig\AnsiExtension;
+use SensioLabs\AnsiConverter\Theme\SolarizedTheme;
+
+$theme = new SolarizedTheme();
+$converter = new AnsiToHtmlConverter($theme, false);
+
+$twig->addExtension(AnsiExtension($converter));
+```
+
+Then:
+
+```jinja
+<html>
+    <head>
+        <style>
+            {# This is only need if the inline styling is disabled #}
+            {{ ansi_css }}
+        </style>
+    </head>
+    <body>
+        {{ some_ansi_code|ansi_to_html }}
+    </body>
+</html>
+```
+

+ 157 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/AnsiToHtmlConverter.php

@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * This file is part of ansi-to-html.
+ *
+ * (c) 2013 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace SensioLabs\AnsiConverter;
+
+use SensioLabs\AnsiConverter\Theme\Theme;
+
+/**
+ * Converts an ANSI text to HTML5.
+ */
+class AnsiToHtmlConverter
+{
+    protected $theme;
+    protected $charset;
+    protected $inlineStyles;
+    protected $inlineColors;
+    protected $colorNames;
+
+    public function __construct(Theme $theme = null, $inlineStyles = true, $charset = 'UTF-8')
+    {
+        $this->theme = null === $theme ? new Theme() : $theme;
+        $this->inlineStyles = $inlineStyles;
+        $this->charset = $charset;
+        $this->inlineColors = $this->theme->asArray();
+        $this->colorNames = array(
+            'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',
+            '', '',
+            'brblack', 'brred', 'brgreen', 'bryellow', 'brblue', 'brmagenta', 'brcyan', 'brwhite',
+        );
+    }
+
+    public function convert($text)
+    {
+        // remove cursor movement sequences
+        $text = preg_replace('#\e\[(K|s|u|2J|2K|\d+(A|B|C|D|E|F|G|J|K|S|T)|\d+;\d+(H|f))#', '', $text);
+        // remove character set sequences
+        $text = preg_replace('#\e(\(|\))(A|B|[0-2])#', '', $text);
+
+        $text = htmlspecialchars($text, PHP_VERSION_ID >= 50400 ? ENT_QUOTES | ENT_SUBSTITUTE : ENT_QUOTES, $this->charset);
+
+        // carriage return
+        $text = preg_replace('#^.*\r(?!\n)#m', '', $text);
+
+        $tokens = $this->tokenize($text);
+
+        // a backspace remove the previous character but only from a text token
+        foreach ($tokens as $i => $token) {
+            if ('backspace' == $token[0]) {
+                $j = $i;
+                while (--$j >= 0) {
+                    if ('text' == $tokens[$j][0] && strlen($tokens[$j][1]) > 0) {
+                        $tokens[$j][1] = substr($tokens[$j][1], 0, -1);
+
+                        break;
+                    }
+                }
+            }
+        }
+
+        $html = '';
+        foreach ($tokens as $token) {
+            if ('text' == $token[0]) {
+                $html .= $token[1];
+            } elseif ('color' == $token[0]) {
+                $html .= $this->convertAnsiToColor($token[1]);
+            }
+        }
+
+        if ($this->inlineStyles) {
+            $html = sprintf('<span style="background-color: %s; color: %s">%s</span>', $this->inlineColors['black'], $this->inlineColors['white'], $html);
+        } else {
+            $html = sprintf('<span class="ansi_color_bg_black ansi_color_fg_white">%s</span>', $html);
+        }
+
+        // remove empty span
+        $html = preg_replace('#<span[^>]*></span>#', '', $html);
+
+        return $html;
+    }
+
+    public function getTheme()
+    {
+        return $this->theme;
+    }
+
+    protected function convertAnsiToColor($ansi)
+    {
+        $bg = 0;
+        $fg = 7;
+        $as = '';
+        if ('0' != $ansi && '' != $ansi) {
+            $options = explode(';', $ansi);
+
+            foreach ($options as $option) {
+                if ($option >= 30 && $option < 38) {
+                    $fg = $option - 30;
+                } elseif ($option >= 40 && $option < 48) {
+                    $bg = $option - 40;
+                } elseif (39 == $option) {
+                    $fg = 7;
+                } elseif (49 == $option) {
+                    $bg = 0;
+                }
+            }
+
+            // options: bold => 1, underscore => 4, blink => 5, reverse => 7, conceal => 8
+            if (in_array(1, $options)) {
+                $fg += 10;
+                $bg += 10;
+            }
+
+            if (in_array(4, $options)) {
+                $as = '; text-decoration: underline';
+            }
+
+            if (in_array(7, $options)) {
+                $tmp = $fg;
+                $fg = $bg;
+                $bg = $tmp;
+            }
+        }
+
+        if ($this->inlineStyles) {
+            return sprintf('</span><span style="background-color: %s; color: %s%s">', $this->inlineColors[$this->colorNames[$bg]], $this->inlineColors[$this->colorNames[$fg]], $as);
+        } else {
+            return sprintf('</span><span class="ansi_color_bg_%s ansi_color_fg_%s">', $this->colorNames[$bg], $this->colorNames[$fg]);
+        }
+    }
+
+    protected function tokenize($text)
+    {
+        $tokens = array();
+        preg_match_all("/(?:\e\[(.*?)m|(\x08))/", $text, $matches, PREG_OFFSET_CAPTURE);
+
+        $offset = 0;
+        foreach ($matches[0] as $i => $match) {
+            if ($match[1] - $offset > 0) {
+                $tokens[] = array('text', substr($text, $offset, $match[1] - $offset));
+            }
+            $tokens[] = array("\x08" == $match[0] ? 'backspace' : 'color', $matches[1][$i][0]);
+            $offset = $match[1] + strlen($match[0]);
+        }
+        if ($offset < strlen($text)) {
+            $tokens[] = array('text', substr($text, $offset));
+        }
+
+        return $tokens;
+    }
+}

+ 48 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Bridge/Twig/AnsiExtension.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace SensioLabs\AnsiConverter\Bridge\Twig;
+
+use SensioLabs\AnsiConverter\AnsiToHtmlConverter;
+use Twig\Extension\AbstractExtension;
+use Twig\TwigFilter;
+use Twig\TwigFunction;
+
+class AnsiExtension extends AbstractExtension
+{
+    /** @var AnsiToHtmlConverter */
+    private $converter;
+
+    public function __construct(AnsiToHtmlConverter $converter = null)
+    {
+        $this->converter = $converter ?: new AnsiToHtmlConverter();
+    }
+
+    public function getFilters(): array
+    {
+        return [
+            new TwigFilter('ansi_to_html', [$this, 'ansiToHtml'], ['is_safe' => ['html']]),
+        ];
+    }
+
+    public function getFunctions(): array
+    {
+        return [
+            new TwigFunction('ansi_css', [$this, 'css'], ['is_safe' => ['css']]),
+        ];
+    }
+
+    public function ansiToHtml($string)
+    {
+        return $this->converter->convert($string);
+    }
+
+    public function css(): string
+    {
+        return $this->converter->getTheme()->asCss();
+    }
+
+    public function getName(): string
+    {
+        return 'sensiolabs_ansi';
+    }
+}

+ 59 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Tests/AnsiToHtmlConverterTest.php

@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of ansi-to-html.
+ *
+ * (c) 2013 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace SensioLabs\AnsiConverter\Tests;
+
+use SensioLabs\AnsiConverter\AnsiToHtmlConverter;
+
+class AnsiToHtmlConverterTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @dataProvider getConvertData
+     */
+    public function testConvert($expected, $input)
+    {
+        $converter = new AnsiToHtmlConverter();
+        $this->assertEquals($expected, $converter->convert($input));
+    }
+
+    public function getConvertData()
+    {
+        return array(
+            // text is escaped
+            array('<span style="background-color: black; color: white">foo &lt;br /&gt;</span>', 'foo <br />'),
+
+            // newlines are preserved
+            array("<span style=\"background-color: black; color: white\">foo\nbar</span>", "foo\nbar"),
+
+            // backspaces
+            array('<span style="background-color: black; color: white">foo   </span>', "foobar\x08\x08\x08   "),
+            array('<span style="background-color: black; color: white">foo</span><span style="background-color: black; color: white">   </span>', "foob\e[31;41ma\e[0mr\x08\x08\x08   "),
+
+            // color
+            array('<span style="background-color: darkred; color: darkred">foo</span>', "\e[31;41mfoo\e[0m"),
+
+            // color with [m as a termination (equivalent to [0m])
+            array('<span style="background-color: darkred; color: darkred">foo</span>', "\e[31;41mfoo\e[m"),
+
+            // bright color
+            array('<span style="background-color: red; color: red">foo</span>', "\e[31;41;1mfoo\e[0m"),
+
+            // carriage returns
+            array('<span style="background-color: black; color: white">foobar</span>', "foo\rbar\rfoobar"),
+
+            // underline
+            array('<span style="background-color: black; color: white; text-decoration: underline">foo</span>', "\e[4mfoo\e[0m"),
+
+            // non valid unicode codepoints substitution (only available with PHP >= 5.4)
+            PHP_VERSION_ID < 50400 ?: array('<span style="background-color: black; color: white">foo '."\xEF\xBF\xBD".'</span>', "foo \xF4\xFF\xFF\xFF"),
+        );
+    }
+}

+ 45 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Theme/SolarizedTheme.php

@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of ansi-to-html.
+ *
+ * (c) 2013 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace SensioLabs\AnsiConverter\Theme;
+
+/**
+ * Solarized theme.
+ *
+ * @see http://ethanschoonover.com/solarized
+ */
+class SolarizedTheme extends Theme
+{
+    public function asArray()
+    {
+        return array(
+            // normal
+            'black' => '#073642',
+            'red' => '#dc322f',
+            'green' => '#859900',
+            'yellow' => '#b58900',
+            'blue' => '#268bd2',
+            'magenta' => '#d33682',
+            'cyan' => '#2aa198',
+            'white' => '#eee8d5',
+
+            // bright
+            'brblack' => '#002b36',
+            'brred' => '#cb4b16',
+            'brgreen' => '#586e75',
+            'bryellow' => '#657b83',
+            'brblue' => '#839496',
+            'brmagenta' => '#6c71c4',
+            'brcyan' => '#93a1a1',
+            'brwhite' => '#fdf6e3',
+        );
+    }
+}

+ 45 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Theme/SolarizedXTermTheme.php

@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of ansi-to-html.
+ *
+ * (c) 2013 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace SensioLabs\AnsiConverter\Theme;
+
+/**
+ * Solarized XTerm theme.
+ *
+ * @see http://ethanschoonover.com/solarized
+ */
+class SolarizedXTermTheme extends Theme
+{
+    public function asArray()
+    {
+        return array(
+            // normal
+            'black' => '#262626',
+            'red' => '#d70000',
+            'green' => '#5f8700',
+            'yellow' => '#af8700',
+            'blue' => '#0087ff',
+            'magenta' => '#af005f',
+            'cyan' => '#00afaf',
+            'white' => '#e4e4e4',
+
+            // bright
+            'brblack' => '#1c1c1c',
+            'brred' => '#d75f00',
+            'brgreen' => '#585858',
+            'bryellow' => '#626262',
+            'brblue' => '#808080',
+            'brmagenta' => '#5f5faf',
+            'brcyan' => '#8a8a8a',
+            'brwhite' => '#ffffd7',
+        );
+    }
+}

+ 52 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/SensioLabs/AnsiConverter/Theme/Theme.php

@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of ansi-to-html.
+ *
+ * (c) 2013 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace SensioLabs\AnsiConverter\Theme;
+
+/**
+ * Base theme.
+ */
+class Theme
+{
+    public function asCss($prefix = 'ansi_color')
+    {
+        $css = array();
+        foreach ($this->asArray() as $name => $color) {
+            $css[] = sprintf('.%s_fg_%s { color: %s }', $prefix, $name, $color);
+            $css[] = sprintf('.%s_bg_%s { background-color: %s }', $prefix, $name, $color);
+        }
+
+        return implode("\n", $css);
+    }
+
+    public function asArray()
+    {
+        return array(
+            'black' => 'black',
+            'red' => 'darkred',
+            'green' => 'green',
+            'yellow' => 'yellow',
+            'blue' => 'blue',
+            'magenta' => 'darkmagenta',
+            'cyan' => 'cyan',
+            'white' => 'white',
+
+            'brblack' => 'black',
+            'brred' => 'red',
+            'brgreen' => 'lightgreen',
+            'bryellow' => 'lightyellow',
+            'brblue' => 'lightblue',
+            'brmagenta' => 'magenta',
+            'brcyan' => 'lightcyan',
+            'brwhite' => 'white',
+        );
+    }
+}

+ 32 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/composer.json

@@ -0,0 +1,32 @@
+{
+    "name": "sensiolabs/ansi-to-html",
+    "type": "library",
+    "description": "A library to convert a text with ANSI codes to HTML",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Fabien Potencier",
+            "email": "[email protected]"
+        }
+    ],
+    "require": {
+        "php": ">=7.2.5"
+    },
+    "require-dev": {
+        "twig/twig": "^2.4 || ^3.0"
+    },
+    "suggest": {
+        "twig/twig": "Provides nice templating features"
+    },
+    "conflict": {
+        "twig/twig": "< 2.4.0"
+    },
+    "autoload": {
+        "psr-4": { "SensioLabs\\AnsiConverter\\": "SensioLabs/AnsiConverter" }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.2-dev"
+        }
+    }
+}

+ 19 - 0
koyeb/web/vendor/sensiolabs/ansi-to-html/phpunit.xml.dist

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit backupGlobals="false"
+         backupStaticAttributes="false"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         stopOnFailure="false"
+         syntaxCheck="false"
+         bootstrap="vendor/autoload.php"
+>
+    <testsuites>
+        <testsuite name="Test Suite">
+            <directory>./SensioLabs/AnsiConverter/Tests</directory>
+        </testsuite>
+    </testsuites>
+</phpunit>

+ 14 - 6
libs/Log.php

@@ -31,16 +31,24 @@ class Log extends Base
     public static function logger()
     {
         if (!self::$loggerInstance instanceof Logger) {
-            // 云函数只能在 /tmp 目录下写文件
+            // 检查日志目录权限
+            $logDir = sprintf('%s/logs/', ROOT_PATH);
+
+            if (!is_writable($logDir)) {
+                system_log(sprintf('由于没有日志目录 %s 的写权限,无法生成日志文件,只能直接输出', $logDir));
+                $stream = 'php://stdout';
+            } else {
+                // 云函数只能在 /tmp 目录下写文件
+                $stream = IS_SCF ? 'php://stdout' : sprintf('%s/logs/%s.log', ROOT_PATH, date('Y-m/d'));
+            }
+
             $handler = new StreamHandler(
-                config('debug') || IS_SCF ? 'php://stdout' : sprintf('%s/logs/%s.log', ROOT_PATH, date('Y-m/d')),
+                $stream,
                 config('debug') ? Logger::DEBUG : Logger::INFO
             );
-            if (config('debug')) {
-                $handler->setFormatter(new ColoredLineFormatter(null, "[%datetime%] %channel%.%level_name%: %message%\n"));
-            }
+            $handler->setFormatter(new ColoredLineFormatter(null, "[%datetime%] %channel%.%level_name%: %message%\n"));
 
-            $logger = new Logger('pusher');
+            $logger = new Logger('ff');
             $logger->pushHandler($handler);
 
             self::$loggerInstance = $logger;

+ 8 - 2
libs/MessageServices/WeChat.php

@@ -119,8 +119,14 @@ class WeChat extends MessageGateway
 
         if (isset($resp['errcode']) && $resp['errcode'] === 0 && isset($resp['access_token']) && isset($resp['expires_in'])) {
             $accessTokenFileText = sprintf("WECHAT_ACCESS_TOKEN=%s\nWECHAT_ACCESS_TOKEN_EXPIRES_AT=%s\n", $resp['access_token'], time() + $resp['expires_in']);
-            if (file_put_contents($this->accessTokenFile, $accessTokenFileText) === false) {
-                throw new \Exception(lang('100113') . $this->accessTokenFile);
+
+            // 检查 Data 目录是否有写入权限
+            if (is_writable(DATA_PATH)) {
+                if (file_put_contents($this->accessTokenFile, $accessTokenFileText) === false) {
+                    throw new \Exception(lang('100113') . $this->accessTokenFile);
+                }
+            } else {
+                system_log('由于 Data 目录没有写入权限,故无法缓存企业微信的 access_token');
             }
 
             return $resp['access_token'];

+ 2 - 3
resources/lang/en.php

@@ -32,9 +32,7 @@ return [
         '100006' => 'Execution error: <red>%s</red>',
         '100007' => 'Cloud function executed successfully.',
         '100008' => 'Cloud function execution failed.',
-        '100009' => 'All environment variables will be read directly from the environment, and those variables not found in the environment will be read directly from the .env.example file, since the current running environment is not a normal VPS',
-        '100010' => 'If it is in the Tencent cloud function, you can refer here to modify or add environment variables without rebuilding: https://github.com/luolongfei/freenom/blob/main/resources/screenshot/scf03.png',
-        '100011' => 'If it is in Aliyun cloud function, you can directly edit the environment variable at [Function Details] -> [Function Configuration] -> [Environment Information]',
+        '100009' => 'It is detected that the current running environment is not a normal VPS or the program does not have read/write access to the project root directory, so all environment variables will be read directly from the environment, and those variables not found in the environment will be read directly from the .env.example file.',
         '100012' => 'Because you did not turn on the upgrade alert feature, you will not be notified when a new version is available. Change the value of NEW_VERSION_DETECTION in the .env file to 1 to turn the feature back on.',
         '100013' => 'Your .env file is too old, the program will automatically update the relevant configuration items according to the .env.example file, don\'t panic, this operation will not have any effect on the existing data',
         '100014' => '<green>Backup of .env file completed</green>, old file location is %s/.env.old',
@@ -154,5 +152,6 @@ return [
         '100132' => 'get ip info error:',
         '100133' => "(If you don't want to get a push every time you execute, adjust the value of NOTICE_FREQ in the .env file to 0 so that the application only pushes when there is a renewal operation.)",
         '100134' => '[Server Info]',
+        '100135' => 'It is detected that the Data directory does not have write permission and cannot record the version number. To avoid repeated pushing of upgrade messages, the program will ignore the version check. Please go to https://github.com/luolongfei/freenom/releases to check if there is a new version by yourself',
     ],
 ];

+ 2 - 3
resources/lang/zh.php

@@ -32,9 +32,7 @@ return [
         '100006' => '执行出错:<red>%s</red>',
         '100007' => '云函数执行成功。',
         '100008' => '云函数执行失败。',
-        '100009' => '检测到当前运行环境非普通 VPS,故所有环境变量将直接从环境中读取,环境中找不到的变量,则直接从 .env.example 文件中读取',
-        '100010' => '如果是在腾讯云函数,可以参考此处修改或新增环境变量,无需重建:https://github.com/luolongfei/freenom/blob/main/resources/screenshot/scf03.png',
-        '100011' => '如果是在阿里云函数,可以直接在【函数详情】->【函数配置】->【环境信息】处编辑环境变量',
+        '100009' => '检测到当前运行环境非普通 VPS 或者程序无项目根目录的读写权限,故所有环境变量将直接从环境中读取,环境中找不到的变量,则直接从 .env.example 文件中读取',
         '100012' => '由于你没有开启升级提醒功能,故无法在有新版本可用时第一时间收到通知。将 .env 文件中 NEW_VERSION_DETECTION 的值改为 1 即可重新开启相关功能。',
         '100013' => '检测到你的 .env 文件内容过旧,程式将根据 .env.example 文件自动更新相关配置项,不要慌张,此操作对已有数据不会有任何影响',
         '100014' => '<green>已完成 .env 文件备份</green>,旧文件位置为 %s/.env.old',
@@ -154,5 +152,6 @@ return [
         '100132' => '获取 ip 信息出错:',
         '100133' => '(如果你不想每次执行都收到推送,请将 .env 中 NOTICE_FREQ 的值设为 0,使程序只在有续期操作时才推送)',
         '100134' => '【服务器信息】',
+        '100135' => '检测到 Data 目录没有写权限,无法记录版本号,为了避免重复推送升级消息,程序将忽略版本检查。请自行前往 https://github.com/luolongfei/freenom/releases 查看是否有新版本',
     ],
 ];

BIN
resources/screenshot/koyeb01.png


Some files were not shown because too many files changed in this diff