├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── gh-pages-deploy.yml ├── .gitignore ├── asset ├── banner │ ├── banner-1400-560.png │ ├── banner-440-280.png │ └── banner-920-680.png ├── logo │ ├── bymeacoffee-48x48.png │ ├── chrome-48x48.png │ └── firefox-48x48.png └── screenshot │ ├── screenshot-001.png │ ├── screenshot-002.json │ ├── screenshot-002.png │ ├── screenshot-003.json │ ├── screenshot-003.png │ ├── screenshot-004.json │ ├── screenshot-004.png │ ├── screenshot-005.gif │ ├── screenshot-005.json │ ├── screenshot-006.gif │ └── screenshot-006.json ├── code_of_conduct.md ├── license ├── package-lock.json ├── package.json ├── readme.md ├── src ├── component │ ├── accentPreset │ │ └── index.js │ ├── accentPresetButton │ │ ├── index.css │ │ └── index.js │ ├── alert │ │ ├── index.css │ │ └── index.js │ ├── base │ │ └── index.js │ ├── body │ │ ├── index.css │ │ └── index.js │ ├── bookmark │ │ ├── index.css │ │ └── index.js │ ├── bookmarkDefault │ │ └── index.js │ ├── bookmarkForm │ │ ├── index.css │ │ └── index.js │ ├── bookmarkMinMax │ │ └── index.js │ ├── bookmarkPreset │ │ └── index.js │ ├── bookmarkPreview │ │ ├── index.css │ │ └── index.js │ ├── button │ │ ├── index.css │ │ └── index.js │ ├── collapse │ │ ├── index.css │ │ └── index.js │ ├── control │ │ ├── checkbox │ │ │ └── index.js │ │ ├── color │ │ │ └── index.js │ │ ├── colorMixer │ │ │ └── index.js │ │ ├── groupText │ │ │ └── index.js │ │ ├── helperText │ │ │ └── index.js │ │ ├── index.js │ │ ├── inputButton │ │ │ └── index.js │ │ ├── radio │ │ │ └── index.js │ │ ├── radioGrid │ │ │ └── index.js │ │ ├── select │ │ │ └── index.js │ │ ├── slider │ │ │ └── index.js │ │ ├── sliderDouble │ │ │ └── index.js │ │ ├── sliderSlim │ │ │ └── index.js │ │ ├── text │ │ │ └── index.js │ │ ├── textReset │ │ │ └── index.js │ │ └── textarea │ │ │ └── index.js │ ├── customTheme │ │ └── index.js │ ├── customThemeDefault │ │ └── index.js │ ├── customThemeForm │ │ └── index.js │ ├── customThemeTile │ │ ├── index.css │ │ └── index.js │ ├── data │ │ └── index.js │ ├── dropFile │ │ ├── index.css │ │ └── index.js │ ├── easterEgg │ │ └── index.js │ ├── fontawesome │ │ ├── index.css │ │ └── index.js │ ├── form │ │ ├── feedback │ │ │ ├── index.css │ │ │ └── index.js │ │ ├── fieldset │ │ │ ├── index.css │ │ │ └── index.js │ │ ├── grid │ │ │ ├── index.css │ │ │ └── index.js │ │ ├── group │ │ │ ├── index.css │ │ │ └── index.js │ │ ├── groupText │ │ │ ├── index.css │ │ │ └── index.js │ │ ├── helper │ │ │ ├── index.css │ │ │ └── index.js │ │ ├── indent │ │ │ ├── index.css │ │ │ └── index.js │ │ ├── index.css │ │ ├── index.js │ │ ├── inline │ │ │ ├── index.css │ │ │ └── index.js │ │ ├── input │ │ │ ├── checkbox │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── color │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── file │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── index.css │ │ │ ├── index.js │ │ │ ├── inputButton │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── number │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── radio │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── range │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── select │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── text │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ └── textarea │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ ├── label │ │ │ ├── index.css │ │ │ └── index.js │ │ ├── sticky │ │ │ ├── index.css │ │ │ └── index.js │ │ └── wrap │ │ │ ├── index.css │ │ │ └── index.js │ ├── grid │ │ ├── index.css │ │ └── index.js │ ├── hexTile │ │ └── index.js │ ├── icon │ │ ├── index.css │ │ └── index.js │ ├── importForm │ │ └── index.js │ ├── index.js │ ├── keyboard │ │ └── index.js │ ├── keyboardShortcut │ │ └── index.js │ ├── layout │ │ ├── index.css │ │ └── index.js │ ├── link │ │ └── index.js │ ├── logo │ │ ├── index.css │ │ └── index.js │ ├── menu │ │ └── index.js │ ├── menuClose │ │ ├── index.css │ │ └── index.js │ ├── menuContent │ │ ├── appSetting │ │ │ └── index.js │ │ ├── bookmarkSetting │ │ │ └── index.js │ │ ├── coffeeSetting │ │ │ └── index.js │ │ ├── dataSetting │ │ │ └── index.js │ │ ├── debugSetting │ │ │ └── index.js │ │ ├── index.css │ │ ├── index.js │ │ ├── layoutSetting │ │ │ └── index.js │ │ ├── supportSetting │ │ │ └── index.js │ │ ├── themeSetting │ │ │ └── index.js │ │ └── toolbarSetting │ │ │ └── index.js │ ├── menuFrame │ │ ├── index.css │ │ └── index.js │ ├── menuNav │ │ ├── index.css │ │ └── index.js │ ├── modal │ │ ├── index.css │ │ └── index.js │ ├── pageLock │ │ └── index.js │ ├── presetThemeTile │ │ ├── index.css │ │ └── index.js │ ├── reset │ │ ├── index.css │ │ └── index.js │ ├── shade │ │ ├── index.css │ │ └── index.js │ ├── splash │ │ ├── index.css │ │ └── index.js │ ├── stagedBookmark │ │ └── index.js │ ├── stagedCustomTheme │ │ └── index.js │ ├── state │ │ └── index.js │ ├── suggest │ │ ├── index.css │ │ └── index.js │ ├── tab │ │ ├── index.css │ │ └── index.js │ ├── theme │ │ ├── index.css │ │ └── index.js │ ├── themePreset │ │ ├── acrid │ │ │ └── index.js │ │ ├── aerial │ │ │ └── index.js │ │ ├── app │ │ │ └── index.js │ │ ├── azure │ │ │ └── index.js │ │ ├── bean │ │ │ └── index.js │ │ ├── black │ │ │ └── index.js │ │ ├── comet │ │ │ └── index.js │ │ ├── corsair │ │ │ └── index.js │ │ ├── dash │ │ │ └── index.js │ │ ├── deco │ │ │ └── index.js │ │ ├── earthquake │ │ │ └── index.js │ │ ├── funkadelic │ │ │ └── index.js │ │ ├── grimm │ │ │ └── index.js │ │ ├── hive │ │ │ └── index.js │ │ ├── hypnos │ │ │ └── index.js │ │ ├── index.js │ │ ├── infrared │ │ │ └── index.js │ │ ├── kapow │ │ │ └── index.js │ │ ├── koto │ │ │ └── index.js │ │ ├── lex │ │ │ └── index.js │ │ ├── macaroon │ │ │ └── index.js │ │ ├── marker │ │ │ └── index.js │ │ ├── midnight │ │ │ └── index.js │ │ ├── mint │ │ │ └── index.js │ │ ├── neon │ │ │ └── index.js │ │ ├── nord │ │ │ └── index.js │ │ ├── obsidian │ │ │ └── index.js │ │ ├── origin │ │ │ └── index.js │ │ ├── outrun │ │ │ └── index.js │ │ ├── pepper │ │ │ └── index.js │ │ ├── point │ │ │ └── index.js │ │ ├── pumpkin │ │ │ └── index.js │ │ ├── replica │ │ │ └── index.js │ │ ├── rumble │ │ │ └── index.js │ │ ├── savage │ │ │ └── index.js │ │ ├── scoria │ │ │ └── index.js │ │ ├── snow │ │ │ └── index.js │ │ ├── sol │ │ │ └── index.js │ │ ├── steel │ │ │ └── index.js │ │ ├── stria │ │ │ └── index.js │ │ ├── terra │ │ │ └── index.js │ │ ├── trine │ │ │ └── index.js │ │ ├── umbra │ │ │ └── index.js │ │ ├── vanadium │ │ │ └── index.js │ │ ├── viper │ │ │ └── index.js │ │ └── white │ │ │ └── index.js │ ├── toolbar │ │ └── index.js │ ├── toolbarControl │ │ ├── index.css │ │ └── index.js │ ├── update │ │ └── index.js │ ├── updateLegacy │ │ └── index.js │ ├── version │ │ └── index.js │ └── video │ │ └── index.js ├── constant │ └── index.js ├── font │ ├── fa │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ └── fa-solid-900.woff2 │ ├── fjalla-one │ │ ├── fjalla-one-400.ttf │ │ ├── fjalla-one-400.woff │ │ └── fjalla-one-400.woff2 │ └── open-sans │ │ ├── open-sans-300.ttf │ │ ├── open-sans-300.woff │ │ ├── open-sans-300.woff2 │ │ ├── open-sans-400.ttf │ │ ├── open-sans-400.woff │ │ ├── open-sans-400.woff2 │ │ ├── open-sans-600.ttf │ │ ├── open-sans-600.woff │ │ ├── open-sans-600.woff2 │ │ ├── open-sans-700.ttf │ │ ├── open-sans-700.woff │ │ ├── open-sans-700.woff2 │ │ ├── open-sans-800.ttf │ │ ├── open-sans-800.woff │ │ ├── open-sans-800.woff2 │ │ ├── open-sans-italic-300.ttf │ │ ├── open-sans-italic-300.woff │ │ ├── open-sans-italic-300.woff2 │ │ ├── open-sans-italic-400.ttf │ │ ├── open-sans-italic-400.woff │ │ ├── open-sans-italic-400.woff2 │ │ ├── open-sans-italic-600.ttf │ │ ├── open-sans-italic-600.woff │ │ ├── open-sans-italic-600.woff2 │ │ ├── open-sans-italic-700.ttf │ │ ├── open-sans-italic-700.woff │ │ ├── open-sans-italic-700.woff2 │ │ ├── open-sans-italic-800.ttf │ │ ├── open-sans-italic-800.woff │ │ └── open-sans-italic-800.woff2 ├── icon │ ├── favicon.svg │ ├── icon-128.png │ ├── icon-16.png │ ├── icon-48.png │ ├── icon-512.png │ └── icon-512.svg ├── index.html ├── index.js ├── initialBackground.js ├── manifest.json ├── style │ ├── animation │ │ └── index.css │ ├── font │ │ └── index.css │ ├── reset │ │ └── index.css │ ├── state │ │ └── index.css │ ├── typography │ │ └── index.css │ ├── utility │ │ └── index.css │ └── zindex │ │ └── index.css └── utility │ ├── applyCSSClass.js │ ├── applyCSSState.js │ ├── applyCSSVar.js │ ├── averageColor.js │ ├── clearChildNode.js │ ├── complexNode.js │ ├── convertColor.js │ ├── dateTime.js │ ├── get.js │ ├── isElementVisible.js │ ├── isJson.js │ ├── isValidString.js │ ├── makePath.js │ ├── minMax.js │ ├── node.js │ ├── ordinalNumber.js │ ├── ordinalWord.js │ ├── randomNumber.js │ ├── randomString.js │ ├── set.js │ ├── sortArrayOfObject.js │ ├── trimString.js │ └── wordNumber.js ├── webpack.common.js ├── webpack.dev.js └── webpack.prod.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | module.exports = { 3 | 'env': { 4 | 'browser': true, 5 | 'es2021': true, 6 | "webextensions": true 7 | }, 8 | 'extends': 'eslint:recommended', 9 | 'ignorePatterns': ['webpack.*', 'dist/'], 10 | 'parserOptions': { 11 | 'ecmaVersion': 12, 12 | 'sourceType': 'module' 13 | }, 14 | 'plugins': ['unused-imports'], 15 | 'rules': { 16 | 'indent': ['error', 2, { 'SwitchCase': 1 }], 17 | 'linebreak-style': [ 18 | 'error', 19 | 'unix' 20 | ], 21 | 'quotes': [ 22 | 'error', 23 | 'single' 24 | ], 25 | 'semi': [ 26 | 'error', 27 | 'always' 28 | ], 29 | 'no-unused-vars': 'off', 30 | 'unused-imports/no-unused-imports': ['error'], 31 | 'unused-imports/no-unused-vars': [ 32 | 'warn', 33 | { 'vars': 'all', 'varsIgnorePattern': '^_', 'args': 'after-used', 'argsIgnorePattern': '^_' } 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages-deploy.yml: -------------------------------------------------------------------------------- 1 | name: gh-pages-deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build-and-deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2.3.1 14 | with: 15 | persist-credentials: false 16 | 17 | - name: Install and Build 18 | run: | 19 | npm install 20 | npm run build 21 | 22 | - name: Deploy 23 | uses: JamesIves/github-pages-deploy-action@4.1.3 24 | with: 25 | branch: gh-pages 26 | folder: dist/web 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | dist 3 | node_modules 4 | -------------------------------------------------------------------------------- /asset/banner/banner-1400-560.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/banner/banner-1400-560.png -------------------------------------------------------------------------------- /asset/banner/banner-440-280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/banner/banner-440-280.png -------------------------------------------------------------------------------- /asset/banner/banner-920-680.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/banner/banner-920-680.png -------------------------------------------------------------------------------- /asset/logo/bymeacoffee-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/logo/bymeacoffee-48x48.png -------------------------------------------------------------------------------- /asset/logo/chrome-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/logo/chrome-48x48.png -------------------------------------------------------------------------------- /asset/logo/firefox-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/logo/firefox-48x48.png -------------------------------------------------------------------------------- /asset/screenshot/screenshot-001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/screenshot/screenshot-001.png -------------------------------------------------------------------------------- /asset/screenshot/screenshot-002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/screenshot/screenshot-002.png -------------------------------------------------------------------------------- /asset/screenshot/screenshot-003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/screenshot/screenshot-003.png -------------------------------------------------------------------------------- /asset/screenshot/screenshot-004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/screenshot/screenshot-004.png -------------------------------------------------------------------------------- /asset/screenshot/screenshot-005.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/screenshot/screenshot-005.gif -------------------------------------------------------------------------------- /asset/screenshot/screenshot-006.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/asset/screenshot/screenshot-006.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hexagonTab", 3 | "version": "4.2.0", 4 | "description": "Hexagon bookmarks accented with a chosen colour. Customise the layout, style, background and bookmarks with hexagonTab.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack serve --open --config webpack.dev.js", 8 | "build": "webpack --config webpack.prod.js", 9 | "lint": "eslint --fix --ext .js ." 10 | }, 11 | "keywords": [ 12 | "startpage", 13 | "start-page", 14 | "newtabpage", 15 | "new-tab-page", 16 | "tab", 17 | "chrome-extension", 18 | "extension", 19 | "bookmarks", 20 | "links", 21 | "hexagonTab" 22 | ], 23 | "author": "zombieFox", 24 | "license": "GPL-3", 25 | "bugs": { 26 | "url": "https://github.com/zombieFox/hexagonTab/issues" 27 | }, 28 | "homepage": "https://github.com/zombieFox/hexagonTab#readme", 29 | "devDependencies": { 30 | "copy-webpack-plugin": "^9.0.1", 31 | "css-loader": "^6.3.0", 32 | "css-minimizer-webpack-plugin": "^3.0.2", 33 | "eslint": "^8.11.0", 34 | "eslint-plugin-unused-imports": "^2.0.0", 35 | "html-webpack-plugin": "^5.3.1", 36 | "mini-css-extract-plugin": "^2.2.0", 37 | "moment": "^2.29.1", 38 | "sortablejs": "^1.13.0", 39 | "style-loader": "^3.3.0", 40 | "terser-webpack-plugin": "^5.1.4", 41 | "webfontloader": "^1.6.28", 42 | "webpack": "^5.37.1", 43 | "webpack-cli": "^4.7.0", 44 | "webpack-dev-server": "^4.2.1", 45 | "webpack-merge": "^5.8.0", 46 | "zip-webpack-plugin": "^4.0.1" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/component/accentPresetButton/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --theme-accent-preset-preview-space: 5; 3 | } 4 | 5 | .theme-accent-preset { 6 | display: grid; 7 | grid-gap: calc((var(--theme-accent-preset-preview-space) / 8) * 1em); 8 | grid-template-columns: repeat(7, auto); 9 | grid-auto-flow: row; 10 | justify-items: center; 11 | width: min-content; 12 | } 13 | 14 | @media (min-width: 550px) { 15 | .theme-accent-preset { 16 | grid-template-rows: repeat(7, auto); 17 | grid-auto-flow: column; 18 | } 19 | } 20 | 21 | .theme-accent-preset-button { 22 | padding: 0; 23 | width: calc((var(--theme-accent-preset-preview-space) / 4) * 1em); 24 | height: calc((var(--theme-accent-preset-preview-space) / 4) * 1em); 25 | min-width: initial; 26 | min-height: initial; 27 | overflow: hidden; 28 | } 29 | 30 | .theme-accent-preset-preview { 31 | background-color: hsl(var(--theme-accent-preset-color-hsl-h), calc(var(--theme-accent-preset-color-hsl-s) * 1%), calc(var(--theme-accent-preset-color-hsl-l) * 1%)); 32 | position: absolute; 33 | top: 0; 34 | left: 0; 35 | width: 100%; 36 | height: 100%; 37 | display: block; 38 | } 39 | -------------------------------------------------------------------------------- /src/component/accentPresetButton/index.js: -------------------------------------------------------------------------------- 1 | import { state } from '../state'; 2 | import { data } from '../data'; 3 | import { toolbar } from '../toolbar'; 4 | import { themeSetting } from '../menuContent/themeSetting'; 5 | 6 | import { Button } from '../button'; 7 | 8 | import { node } from '../../utility/node'; 9 | import { convertColor } from '../../utility/convertColor'; 10 | import { applyCSSVar } from '../../utility/applyCSSVar'; 11 | 12 | import './index.css'; 13 | 14 | export const AccentPresetButton = function({ presetData = false } = {}) { 15 | 16 | this.name = () => { 17 | 18 | let fullName = presetData.name; 19 | 20 | if (presetData.prefix) { 21 | fullName = presetData.prefix + ' ' + presetData.name.toLowerCase(); 22 | } 23 | 24 | return fullName; 25 | 26 | }; 27 | 28 | this.element = { 29 | button: new Button({ 30 | text: this.name(), 31 | title: this.name(), 32 | srOnly: true, 33 | classList: ['theme-accent-preset-button', 'theme-accent-preset-type-' + presetData.type], 34 | func: () => { 35 | 36 | state.get.current().theme.accent.rgb = convertColor.hsl.rgb(presetData.hsl); 37 | 38 | state.get.current().theme.accent.hsl = presetData.hsl; 39 | 40 | applyCSSVar([ 41 | 'theme.accent.rgb.r', 42 | 'theme.accent.rgb.g', 43 | 'theme.accent.rgb.b', 44 | 'theme.accent.hsl.h', 45 | 'theme.accent.hsl.s', 46 | 'theme.accent.hsl.l' 47 | ]); 48 | 49 | toolbar.current.update.style(); 50 | 51 | toolbar.current.update.accent(); 52 | 53 | themeSetting.control.accent.color.update(); 54 | 55 | data.save(); 56 | 57 | } 58 | }), 59 | preview: node('span|class:theme-accent-preset-preview') 60 | }; 61 | 62 | this.previewTile = () => { 63 | 64 | this.element.preview.style.setProperty('--theme-accent-preset-color-hsl-h', presetData.hsl.h); 65 | 66 | this.element.preview.style.setProperty('--theme-accent-preset-color-hsl-s', presetData.hsl.s); 67 | 68 | this.element.preview.style.setProperty('--theme-accent-preset-color-hsl-l', presetData.hsl.l); 69 | 70 | }; 71 | 72 | this.assemble = () => { 73 | 74 | this.previewTile(); 75 | 76 | this.element.button.button.appendChild(this.element.preview); 77 | 78 | }; 79 | 80 | this.button = () => { 81 | 82 | return this.element.button.button; 83 | 84 | }; 85 | 86 | this.assemble(); 87 | 88 | }; 89 | -------------------------------------------------------------------------------- /src/component/alert/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --alert-space: 4; 3 | } 4 | 5 | :root { 6 | --alert-header-background: var(--theme-primary-030); 7 | --alert-body-background: var(--theme-primary-020); 8 | } 9 | 10 | .alert { 11 | width: 100%; 12 | display: flex; 13 | flex-direction: row; 14 | } 15 | 16 | .alert-header { 17 | background-color: hsl(var(--alert-header-background)); 18 | padding: calc((var(--alert-space) / 4) * 1em) calc((var(--alert-space) / 4) * 1em) calc((var(--alert-space) / 4) * 1em) calc(((var(--alert-space) / 4) * 1em) + (var(--theme-radius) / 100) * 0.1em); 19 | border-top-left-radius: calc(var(--theme-radius) * 0.01em); 20 | border-bottom-left-radius: calc(var(--theme-radius) * 0.01em); 21 | display: flex; 22 | flex-direction: row; 23 | align-items: center; 24 | transition: background-color var(--layout-transition-extra-fast); 25 | } 26 | 27 | .alert-body { 28 | background-color: hsl(var(--alert-body-background)); 29 | border-top-right-radius: calc(var(--theme-radius) * 0.01em); 30 | border-bottom-right-radius: calc(var(--theme-radius) * 0.01em); 31 | padding: calc((var(--alert-space) / 4) * 1em) calc(((var(--alert-space) / 4) * 1em) + (var(--theme-radius) / 100) * 0.1em) calc((var(--alert-space) / 4) * 1em) calc((var(--alert-space) / 4) * 1em); 32 | flex-grow: 1; 33 | display: flex; 34 | flex-direction: row; 35 | align-items: center; 36 | transition: background-color var(--layout-transition-extra-fast); 37 | } 38 | 39 | .alert-body:only-child { 40 | border-radius: calc(var(--theme-radius) * 0.01em); 41 | padding: calc((var(--alert-space) / 4) * 1em) calc(((var(--alert-space) / 4) * 1em) + (var(--theme-radius) / 100) * 0.1em); 42 | } 43 | 44 | .alert-icon { 45 | font-size: 1em; 46 | } 47 | -------------------------------------------------------------------------------- /src/component/alert/index.js: -------------------------------------------------------------------------------- 1 | import { icon } from '../icon'; 2 | 3 | import * as form from '../form'; 4 | 5 | import { node } from '../../utility/node'; 6 | 7 | import './index.css'; 8 | 9 | export const Alert = function({ 10 | children = [], 11 | iconName = false 12 | } = {}) { 13 | 14 | this.element = { 15 | alert: node('div|class:alert'), 16 | header: node('div|class:alert-header'), 17 | body: node('div|class:alert-body'), 18 | icon: node('div|class:alert-icon'), 19 | message: node('div|class:alert-message', children) 20 | }; 21 | 22 | this.assemble = () => { 23 | 24 | if (iconName) { 25 | 26 | this.element.icon.appendChild(icon.render(iconName)); 27 | 28 | this.element.header.appendChild(this.element.icon); 29 | 30 | this.element.alert.appendChild(this.element.header); 31 | 32 | } 33 | 34 | this.element.body.appendChild(this.element.message); 35 | 36 | this.element.alert.appendChild(this.element.body); 37 | 38 | }; 39 | 40 | this.alert = () => { 41 | return this.element.alert; 42 | }; 43 | 44 | this.wrap = () => { 45 | return form.wrap({ 46 | children: [ 47 | this.element.alert 48 | ] 49 | }); 50 | }; 51 | 52 | this.assemble(); 53 | 54 | }; 55 | -------------------------------------------------------------------------------- /src/component/base/index.js: -------------------------------------------------------------------------------- 1 | // must be loaded first 2 | import '../../style/reset/index.css'; 3 | 4 | // base styles for all components 5 | import '../../style/animation/index.css'; 6 | import '../../style/font/index.css'; 7 | import '../../style/state/index.css'; 8 | import '../../style/typography/index.css'; 9 | import '../../style/zindex/index.css'; 10 | import '../../style/utility/index.css'; 11 | 12 | export const base = {}; 13 | -------------------------------------------------------------------------------- /src/component/body/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --base-size: 12; 3 | --font-size: calc(var(--base-size) * 1px); 4 | } 5 | 6 | @media (min-width: 900px) { 7 | :root { 8 | --base-size: 16; 9 | } 10 | } 11 | 12 | ::selection { 13 | background-color: rgb(var(--theme-accent)); 14 | color: hsl(var(--theme-accent-text)); 15 | } 16 | 17 | html, 18 | body { 19 | background-color: hsl(var(--theme-primary-010)); 20 | font-size: var(--font-size); 21 | line-height: 1.6; 22 | font-family: var(--theme-font-ui-name); 23 | font-weight: var(--theme-font-ui-weight); 24 | font-style: var(--theme-font-ui-style); 25 | color: hsl(var(--theme-primary-text-010)); 26 | transition: background-color var(--layout-transition-extra-fast); 27 | } 28 | 29 | body { 30 | min-height: 100vh; 31 | display: flex; 32 | flex-direction: column; 33 | justify-content: center; 34 | align-items: center; 35 | } 36 | 37 | html.is-theme-style-dark, 38 | .is-theme-style-dark body, 39 | html.is-theme-style-light, 40 | .is-theme-style-light body { 41 | background-color: hsl(var(--theme-primary-010)); 42 | color: hsl(var(--theme-primary-text-010)); 43 | } 44 | 45 | @media (prefers-color-scheme: light) { 46 | 47 | html.is-theme-style-system, 48 | .is-theme-style-system body { 49 | background-color: hsl(var(--theme-primary-010)); 50 | color: hsl(var(--theme-primary-text-010)); 51 | } 52 | } 53 | 54 | @media (prefers-color-scheme: dark) { 55 | 56 | html.is-theme-style-system, 57 | .is-theme-style-system body { 58 | background-color: hsl(var(--theme-primary-010)); 59 | color: hsl(var(--theme-primary-text-010)); 60 | } 61 | } 62 | 63 | html.is-theme-background-type-theme, 64 | .is-theme-background-type-theme body { 65 | background-color: hsl(var(--theme-background-theme)); 66 | } 67 | 68 | html.is-theme-background-type-accent, 69 | .is-theme-background-type-accent body { 70 | background-color: rgb(var(--theme-background-accent)); 71 | } 72 | 73 | html.is-theme-background-type-color, 74 | .is-theme-background-type-color body { 75 | background-color: rgb(var(--theme-background-color)); 76 | } 77 | -------------------------------------------------------------------------------- /src/component/body/index.js: -------------------------------------------------------------------------------- 1 | import './index.css'; 2 | 3 | export const body = {}; 4 | -------------------------------------------------------------------------------- /src/component/bookmarkDefault/index.js: -------------------------------------------------------------------------------- 1 | export const bookmarkDefault = { 2 | url: '', 3 | display: { 4 | direction: 'vertical', 5 | order: 'visual-name', 6 | rotate: 0, 7 | translate: { x: 0, y: 0 }, 8 | gutter: 25, 9 | name: { show: true, text: '', size: 7 }, 10 | visual: { show: true, type: 'letter', size: 25, letter: { text: '' }, icon: { name: '', prefix: '', label: '' }, image: { url: '' } } 11 | }, 12 | accent: { by: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } }, 13 | color: { by: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 }, opacity: 100 }, 14 | background: { show: false, type: 'image', opacity: 100, image: { url: '' }, video: { url: '' } }, 15 | timestamp: null 16 | }; 17 | -------------------------------------------------------------------------------- /src/component/bookmarkForm/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --bookmark-form-space: calc((var(--form-space) / 4) * 1em); 3 | } 4 | 5 | .bookmark-form { 6 | display: block; 7 | } 8 | 9 | @media (min-width: 900px) { 10 | .bookmark-form { 11 | display: grid; 12 | grid-template-columns: 6fr 2fr; 13 | gap: var(--bookmark-form-space); 14 | align-items: stretch; 15 | min-height: 60vh; 16 | } 17 | } 18 | 19 | .bookmark-form-main { 20 | padding-bottom: var(--bookmark-form-space); 21 | } 22 | 23 | .bookmark-form-aside { 24 | display: none; 25 | } 26 | 27 | @media (min-width: 900px) { 28 | .bookmark-form-aside { 29 | display: block; 30 | } 31 | } 32 | 33 | .bookmark-form-text-icon { 34 | position: relative; 35 | } 36 | 37 | .bookmark-form-text-icon:empty:before { 38 | content: ""; 39 | background-color: hsl(var(--theme-primary-040)); 40 | top: 50%; 41 | left: 50%; 42 | position: absolute; 43 | width: 0.5em; 44 | height: 0.5em; 45 | border-radius: 50%; 46 | display: block; 47 | transform: translate(-50%, -50%); 48 | } 49 | 50 | .bookmark-form-text-icon .bookmark-form-icon { 51 | transform: scale(1) rotate(0deg); 52 | transition: transform var(--layout-transition-extra-fast); 53 | } 54 | 55 | .bookmark-form-text-icon:not(.disabled):hover .bookmark-form-icon { 56 | transform: scale(2) rotate(360deg); 57 | z-index: 1; 58 | } 59 | 60 | .bookmark-form-text-icon:not(.disabled):active .bookmark-form-icon { 61 | transform: scale(4) rotate(360deg); 62 | } 63 | 64 | .bookmark-form-icon { 65 | font-size: 1.5em; 66 | } 67 | -------------------------------------------------------------------------------- /src/component/bookmarkMinMax/index.js: -------------------------------------------------------------------------------- 1 | export const bookmarkMinMax = { 2 | display: { 3 | rotate: { min: -180, max: 180 }, 4 | translate: { x: { min: -300, max: 300 }, y: { min: -300, max: 300 } }, 5 | gutter: { min: 0, max: 500 }, 6 | visual: { size: { min: 5, max: 400 } }, 7 | name: { size: { min: 5, max: 400 } } 8 | }, 9 | accent: { 10 | hsl: { h: { min: 0, max: 359 }, s: { min: 0, max: 100 }, l: { min: 0, max: 100 } }, 11 | rgb: { r: { min: 0, max: 255 }, g: { min: 0, max: 255 }, b: { min: 0, max: 255 } } 12 | }, 13 | color: { 14 | hsl: { h: { min: 0, max: 359 }, s: { min: 0, max: 100 }, l: { min: 0, max: 100 } }, 15 | rgb: { r: { min: 0, max: 255 }, g: { min: 0, max: 255 }, b: { min: 0, max: 255 } }, 16 | opacity: { min: 0, max: 100 } 17 | }, 18 | background: { 19 | opacity: { min: 0, max: 100 } 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /src/component/bookmarkPreview/index.css: -------------------------------------------------------------------------------- 1 | .bookmark-preview-area { 2 | position: sticky; 3 | top: 50%; 4 | transform: translateY(-50%); 5 | display: grid; 6 | justify-items: center; 7 | gap: 1em; 8 | grid-template-rows: auto auto; 9 | } 10 | 11 | .bookmark-preview-grid { 12 | display: block; 13 | width: 100%; 14 | transition: background-color var(--layout-transition-extra-fast); 15 | } 16 | 17 | .bookmark.bookmark-preview { 18 | pointer-events: none; 19 | } 20 | 21 | .bookmark.bookmark-preview .bookmark-control { 22 | display: none; 23 | } 24 | 25 | .bookmark.bookmark-preview .bookmark-display { 26 | font-size: 1em; 27 | } 28 | 29 | .bookmark.bookmark-preview .bookmark-shadow-wrap { 30 | display: none; 31 | } 32 | -------------------------------------------------------------------------------- /src/component/bookmarkPreview/index.js: -------------------------------------------------------------------------------- 1 | import { HexTile } from '../hexTile'; 2 | 3 | import { node } from '../../utility/node'; 4 | 5 | import './index.css'; 6 | 7 | export const BookmarkPreview = function({ 8 | bookmarkData = false 9 | } = {}) { 10 | 11 | this.area = node('div|class:bookmark-preview-area'); 12 | 13 | this.grid = node('div|class:bookmark-preview-grid'); 14 | 15 | this.title = node('div:Preview|class:bookmark-preview-title small muted'); 16 | 17 | this.bookmarkTile = new HexTile({ 18 | bookmarkData: bookmarkData, 19 | preview: true 20 | }); 21 | 22 | this.update = {}; 23 | 24 | this.update.style = (newBookmarkData) => { 25 | bookmarkData = newBookmarkData; 26 | 27 | this.bookmarkTile.update(); 28 | 29 | }; 30 | 31 | this.update.assemble = (newBookmarkData) => { 32 | bookmarkData = newBookmarkData; 33 | 34 | this.area.removeChild(this.title); 35 | 36 | this.grid.removeChild(this.bookmarkTile.tile()); 37 | 38 | this.bookmarkTile = new HexTile({ 39 | bookmarkData: bookmarkData, 40 | preview: true 41 | }); 42 | 43 | this.assemble(); 44 | }; 45 | 46 | this.assemble = () => { 47 | this.area.appendChild(this.title); 48 | 49 | this.grid.appendChild(this.bookmarkTile.tile()); 50 | 51 | this.area.appendChild(this.grid); 52 | }; 53 | 54 | this.assemble(); 55 | 56 | this.preview = () => { 57 | return this.area; 58 | }; 59 | 60 | }; 61 | -------------------------------------------------------------------------------- /src/component/collapse/index.css: -------------------------------------------------------------------------------- 1 | .collapse { 2 | margin-top: calc(var(--wrap-space) * -1); 3 | position: relative; 4 | display: grid; 5 | transition: margin var(--layout-transition-fast); 6 | pointer-events: none; 7 | } 8 | 9 | .collapse-area { 10 | margin-top: calc(var(--wrap-space) - 1em); 11 | margin-right: -1em; 12 | margin-bottom: -1em; 13 | margin-left: -1em; 14 | position: relative; 15 | display: block; 16 | overflow: hidden; 17 | transition: margin var(--layout-transition-fast); 18 | } 19 | 20 | .collapse-area.is-collapsed { 21 | margin: 0; 22 | } 23 | 24 | .collapse-spacer { 25 | padding: 1em; 26 | transition: margin var(--layout-transition-fast); 27 | } 28 | 29 | .collapse-spacer>* { 30 | pointer-events: all; 31 | } 32 | 33 | .collapse-area.is-collapsed .collapse-spacer { 34 | margin-bottom: -200vh; 35 | position: relative; 36 | } 37 | 38 | .collapse-toggle .icon { 39 | transition: transform var(--layout-transition-fast); 40 | } 41 | 42 | .collapse-toggle.is-collapsed .icon { 43 | transform: rotate(180deg); 44 | } 45 | 46 | .collapse-spacer hr:first-child { 47 | margin-top: var(--wrap-space); 48 | } 49 | 50 | /* debug */ 51 | /* .collapse { 52 | outline: 1px dotted blue; 53 | } 54 | 55 | .collapse-area { 56 | outline: 1px solid red; 57 | } */ 58 | -------------------------------------------------------------------------------- /src/component/control/checkbox/index.js: -------------------------------------------------------------------------------- 1 | 2 | import * as form from '../../form'; 3 | 4 | 5 | import { get } from '../../../utility/get'; 6 | import { set } from '../../../utility/set'; 7 | 8 | export const Control_checkbox = function({ 9 | object = {}, 10 | id = 'name', 11 | path = false, 12 | labelText = 'name', 13 | description = false, 14 | action = false 15 | } = {}) { 16 | 17 | this.checkbox = form.input.checkbox({ 18 | id: id, 19 | checked: get({ object: object, path: path }), 20 | func: () => { 21 | 22 | set({ object: object, path: path, value: this.checkbox.checked }); 23 | 24 | if (action) { action(); } 25 | 26 | } 27 | }); 28 | 29 | this.label = form.label({ 30 | forInput: id, 31 | text: labelText, 32 | description: description, 33 | icon: true 34 | }); 35 | 36 | this.update = () => { 37 | this.checkbox.checked = get({ object: object, path: path }); 38 | }; 39 | 40 | this.checked = () => { 41 | 42 | return get({ object: object, path: path }); 43 | 44 | }; 45 | 46 | this.wrap = () => { 47 | 48 | return form.wrap({ 49 | children: [ 50 | this.checkbox, 51 | this.label 52 | ] 53 | }); 54 | 55 | }; 56 | 57 | this.disable = () => { 58 | this.checkbox.disabled = true; 59 | }; 60 | 61 | this.enable = () => { 62 | this.checkbox.disabled = false; 63 | }; 64 | 65 | }; 66 | -------------------------------------------------------------------------------- /src/component/control/groupText/index.js: -------------------------------------------------------------------------------- 1 | 2 | import * as form from '../../form'; 3 | 4 | 5 | import { isValidString } from '../../../utility/isValidString'; 6 | import { clearChildNode } from '../../../utility/clearChildNode'; 7 | 8 | export const Control_groupText = function({ 9 | text = false, 10 | classList = [] 11 | } = {}) { 12 | 13 | this.groupText = form.groupText({ 14 | text: text, 15 | classList: classList 16 | }); 17 | 18 | this.update = (content) => { 19 | 20 | clearChildNode(this.groupText); 21 | 22 | if (typeof content === 'string' && isValidString(content)) { 23 | this.groupText.textContent = content; 24 | } else if (content && content != '') { 25 | this.groupText.appendChild(content); 26 | } 27 | }; 28 | 29 | this.wrap = () => { 30 | return form.wrap({ 31 | children: [ 32 | this.groupText 33 | ] 34 | }); 35 | }; 36 | 37 | this.disable = () => { 38 | this.groupText.classList.add('disabled'); 39 | }; 40 | 41 | this.enable = () => { 42 | this.groupText.classList.remove('disabled'); 43 | }; 44 | 45 | }; 46 | -------------------------------------------------------------------------------- /src/component/control/helperText/index.js: -------------------------------------------------------------------------------- 1 | 2 | import * as form from '../../form'; 3 | 4 | 5 | 6 | export const Control_helperText = function({ 7 | text = [], 8 | complexText= false 9 | } = {}) { 10 | 11 | this.para = []; 12 | 13 | text.forEach(item => { 14 | this.para.push(form.helper({ 15 | tag: 'p', 16 | text: item, 17 | complexText: complexText 18 | })); 19 | }); 20 | 21 | this.wrap = () => { 22 | const formWrap = form.wrap(); 23 | 24 | this.para.forEach(item => { 25 | formWrap.appendChild(item); 26 | }); 27 | 28 | return formWrap; 29 | }; 30 | 31 | this.disable = () => { 32 | this.para.forEach(item => { 33 | item.classList.add('disabled'); 34 | }); 35 | }; 36 | 37 | this.enable = () => { 38 | this.para.forEach(item => { 39 | item.classList.remove('disabled'); 40 | }); 41 | }; 42 | 43 | }; 44 | -------------------------------------------------------------------------------- /src/component/control/index.js: -------------------------------------------------------------------------------- 1 | import { Control_checkbox } from './checkbox'; 2 | import { Control_color } from './color'; 3 | import { Control_colorMixer } from './colorMixer'; 4 | import { Control_groupText } from './groupText'; 5 | import { Control_helperText } from './helperText'; 6 | import { Control_inputButton } from './inputButton'; 7 | import { Control_radio } from './radio'; 8 | import { Control_radioGrid } from './radioGrid'; 9 | import { Control_slider } from './slider'; 10 | import { Control_sliderSlim } from './sliderSlim'; 11 | import { Control_sliderDouble } from './sliderDouble'; 12 | import { Control_text } from './text'; 13 | import { Control_select } from './select'; 14 | 15 | export { 16 | Control_checkbox, 17 | Control_color, 18 | Control_colorMixer, 19 | Control_groupText, 20 | Control_helperText, 21 | Control_inputButton, 22 | Control_radio, 23 | Control_radioGrid, 24 | Control_slider, 25 | Control_sliderSlim, 26 | Control_sliderDouble, 27 | Control_text, 28 | Control_select 29 | }; 30 | -------------------------------------------------------------------------------- /src/component/control/select/index.js: -------------------------------------------------------------------------------- 1 | 2 | import * as form from '../../form'; 3 | 4 | 5 | import { complexNode } from '../../../utility/complexNode'; 6 | import { get } from '../../../utility/get'; 7 | import { set } from '../../../utility/set'; 8 | import { trimString } from '../../../utility/trimString'; 9 | import { clearChildNode } from '../../../utility/clearChildNode'; 10 | 11 | export const Control_select = function({ 12 | option = [], 13 | selected = 0, 14 | object = {}, 15 | id = 'name', 16 | path = false, 17 | labelText = 'name', 18 | srOnly = false, 19 | description = false, 20 | action = false 21 | } = {}) { 22 | 23 | this.select = form.input.select({ 24 | id: id, 25 | option: option, 26 | selected: selected, 27 | func: () => { 28 | 29 | set({ object: object, path: path, value: this.select.selectedIndex }); 30 | 31 | if (action) { action(); } 32 | 33 | } 34 | }); 35 | 36 | this.label = form.label({ 37 | forInput: id, 38 | text: labelText, 39 | description: description 40 | }); 41 | 42 | if (srOnly) { 43 | this.label.classList.add('sr-only'); 44 | } 45 | 46 | this.update = () => { 47 | this.select.selectedIndex = get({ 48 | object: object, 49 | path: path 50 | }); 51 | }; 52 | 53 | this.updateOption = (option, selectedIndex) => { 54 | 55 | if (option.length > 0) { 56 | 57 | clearChildNode(this.select); 58 | 59 | option.forEach(item => { 60 | 61 | this.select.appendChild( 62 | complexNode({ 63 | tag: 'option', 64 | text: item, 65 | attr: [{ 66 | key: 'value', 67 | value: trimString(item).replace(/\s+/g, '-').toLowerCase() 68 | }] 69 | }) 70 | ); 71 | 72 | }); 73 | 74 | if (selectedIndex || selectedIndex === 0) { 75 | this.select.selectedIndex = selectedIndex; 76 | } 77 | 78 | } 79 | 80 | }; 81 | 82 | this.selected = () => { 83 | return this.select.selectedIndex; 84 | }; 85 | 86 | this.wrap = () => { 87 | return form.wrap({ 88 | children: [ 89 | this.label, 90 | this.select 91 | ] 92 | }); 93 | }; 94 | 95 | this.disable = () => { 96 | this.label.classList.add('disabled'); 97 | this.select.disabled = true; 98 | }; 99 | 100 | this.enable = () => { 101 | this.label.classList.remove('disabled'); 102 | this.select.disabled = false; 103 | }; 104 | 105 | }; 106 | -------------------------------------------------------------------------------- /src/component/control/text/index.js: -------------------------------------------------------------------------------- 1 | 2 | import * as form from '../../form'; 3 | 4 | 5 | import { get } from '../../../utility/get'; 6 | import { set } from '../../../utility/set'; 7 | 8 | export const Control_text = function({ 9 | object = {}, 10 | path = false, 11 | id = 'name', 12 | value = false, 13 | min = false, 14 | max = false, 15 | placeholder = false, 16 | classList = [], 17 | labelText = 'Name', 18 | srOnly = false, 19 | action = false 20 | } = {}) { 21 | 22 | this.label = form.label({ 23 | forInput: id, 24 | text: labelText 25 | }); 26 | 27 | if (srOnly) { 28 | this.label.classList.add('sr-only'); 29 | } 30 | 31 | this.text = form.input.text({ 32 | id: id, 33 | classList: classList, 34 | func: () => { 35 | 36 | if (path) { 37 | set({ object: object, path: path, value: this.text.value }); 38 | } 39 | 40 | if (action) { action(); } 41 | 42 | } 43 | }); 44 | 45 | if (value) { 46 | this.text.value = value; 47 | } 48 | 49 | if (min) { 50 | this.text.min = min; 51 | } 52 | 53 | if (max) { 54 | this.text.max = max; 55 | } 56 | 57 | if (placeholder) { 58 | this.text.placeholder = placeholder; 59 | } 60 | 61 | this.update = () => { 62 | 63 | this.text.value = get({ object: object, path: path }); 64 | 65 | }; 66 | 67 | this.wrap = () => { 68 | return form.wrap({ 69 | children: [ 70 | this.label, 71 | this.text 72 | ] 73 | }); 74 | }; 75 | 76 | this.disable = () => { 77 | this.label.classList.add('disabled'); 78 | this.text.disabled = true; 79 | }; 80 | 81 | this.enable = () => { 82 | this.label.classList.remove('disabled'); 83 | this.text.disabled = false; 84 | }; 85 | 86 | }; 87 | -------------------------------------------------------------------------------- /src/component/control/textarea/index.js: -------------------------------------------------------------------------------- 1 | 2 | import * as form from '../../form'; 3 | 4 | 5 | import { get } from '../../../utility/get'; 6 | import { set } from '../../../utility/set'; 7 | 8 | export const Control_textarea = function({ 9 | object = {}, 10 | path = false, 11 | id = 'name', 12 | value = false, 13 | min = false, 14 | max = false, 15 | placeholder = false, 16 | classList = [], 17 | labelText = 'Name', 18 | srOnly = false, 19 | action = false 20 | } = {}) { 21 | 22 | this.label = form.label({ 23 | forInput: id, 24 | text: labelText 25 | }); 26 | 27 | if (srOnly) { 28 | this.label.classList.add('sr-only'); 29 | } 30 | 31 | this.textarea = form.input.textarea({ 32 | id: id, 33 | classList: classList, 34 | func: () => { 35 | 36 | if (path) { 37 | set({ object: object, path: path, value: this.textarea.value }); 38 | } 39 | 40 | if (action) { action(); } 41 | 42 | } 43 | }); 44 | 45 | if (value) { 46 | this.textarea.value = value; 47 | } 48 | 49 | if (min) { 50 | this.textarea.minLength = min; 51 | } 52 | 53 | if (max) { 54 | this.textarea.maxLength = max; 55 | } 56 | 57 | if (placeholder) { 58 | this.textarea.placeholder = placeholder; 59 | } 60 | 61 | this.update = () => { 62 | 63 | this.textarea.value = get({ object: object, path: path }); 64 | 65 | }; 66 | 67 | this.wrap = () => { 68 | return form.wrap({ 69 | children: [ 70 | this.label, 71 | this.textarea 72 | ] 73 | }); 74 | }; 75 | 76 | this.disable = () => { 77 | this.label.classList.add('disabled'); 78 | this.textarea.disabled = true; 79 | }; 80 | 81 | this.enable = () => { 82 | this.label.classList.remove('disabled'); 83 | this.textarea.disabled = false; 84 | }; 85 | 86 | }; 87 | -------------------------------------------------------------------------------- /src/component/customThemeDefault/index.js: -------------------------------------------------------------------------------- 1 | import { state } from '../state'; 2 | 3 | export const customThemeDefault = () => { 4 | return { 5 | name: '', 6 | color: { range: { primary: { h: state.get.current().theme.color.range.primary.h, s: state.get.current().theme.color.range.primary.s } }, contrast: state.get.current().theme.color.contrast }, 7 | accent: { hsl: state.get.current().theme.accent.hsl, rgb: state.get.current().theme.accent.rgb }, 8 | font: state.get.current().theme.font, 9 | background: state.get.current().theme.background, 10 | style: state.get.current().theme.style, 11 | shade: state.get.current().theme.shade, 12 | bookmark: state.get.current().theme.bookmark, 13 | toolbar: state.get.current().theme.toolbar 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /src/component/customThemeForm/index.js: -------------------------------------------------------------------------------- 1 | 2 | import { Button } from '../button'; 3 | 4 | import { Control_text } from '../control/text'; 5 | 6 | import { node } from '../../utility/node'; 7 | import { randomString } from '../../utility/randomString'; 8 | import { randomNumber } from '../../utility/randomNumber'; 9 | 10 | export const CustomThemeForm = function({ 11 | customThemeData = false 12 | } = {}) { 13 | 14 | this.element = { 15 | form: node('form|class:theme-custom-form'), 16 | main: node('div|class:theme-custom-form-main'), 17 | text: new Control_text({ 18 | object: customThemeData.theme, 19 | path: 'name', 20 | id: 'name', 21 | value: customThemeData.theme.name, 22 | placeholder: 'Example theme', 23 | labelText: 'Name' 24 | }), 25 | randomName: new Button({ 26 | text: 'Random theme name', 27 | style: ['line'], 28 | func: () => { 29 | customThemeData.theme.name = randomString({ adjectivesCount: randomNumber(1, 3) }); 30 | this.element.text.update(); 31 | } 32 | }) 33 | }; 34 | 35 | this.assemble = () => { 36 | 37 | this.element.main.appendChild(this.element.text.wrap()); 38 | 39 | this.element.main.appendChild(this.element.randomName.wrap()); 40 | 41 | this.element.form.appendChild(this.element.main); 42 | 43 | }; 44 | 45 | this.form = () => { 46 | 47 | return this.element.form; 48 | 49 | }; 50 | 51 | this.assemble(); 52 | 53 | }; 54 | -------------------------------------------------------------------------------- /src/component/dropFile/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --drop-file-space: 24; 3 | } 4 | 5 | :root { 6 | --drop-file-background: var(--theme-primary-030); 7 | --drop-file-border: var(--theme-primary-030); 8 | --drop-file-border-focus-hover: var(--theme-accent); 9 | } 10 | 11 | .drop-file { 12 | border-width: calc(var(--layout-line-width) * 2); 13 | border-style: solid; 14 | border-color: hsl(var(--drop-file-border)); 15 | border-radius: calc(var(--theme-radius) * 0.01em); 16 | padding: calc(((var(--alert-space) * 2) / 4) * 1em) calc((var(--alert-space) / 4) * 1em); 17 | width: 100%; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | justify-content: center; 22 | gap: 1em; 23 | transform: scale(1); 24 | transition: background-color var(--layout-transition-extra-fast), border var(--layout-transition-extra-fast), transform var(--layout-transition-extra-fast); 25 | } 26 | 27 | .drop-file-heading {} 28 | 29 | .drop-file-over { 30 | background: hsl(var(--drop-file-background)); 31 | border-color: rgb(var(--drop-file-border-focus-hover)); 32 | transform: scale(1.05); 33 | } 34 | -------------------------------------------------------------------------------- /src/component/dropFile/index.js: -------------------------------------------------------------------------------- 1 | 2 | import * as form from '../form'; 3 | 4 | import { node } from '../../utility/node'; 5 | 6 | import './index.css'; 7 | 8 | export const DropFile = function({ 9 | heading = 'Drop file here', 10 | dropAaction = false, 11 | enterAction = false, 12 | leaveAction = false, 13 | children = [] 14 | } = {}) { 15 | 16 | this.files = false; 17 | 18 | this.element = { 19 | drop: node('div|class:drop-file', children), 20 | heading: node(`p:${heading}|class:drop-file-heading small`) 21 | }; 22 | 23 | this.assemble = () => { 24 | 25 | this.element.drop.appendChild(this.element.heading); 26 | 27 | }; 28 | 29 | this.bind = () => { 30 | 31 | this.element.drop.addEventListener('dragenter', (event) => { 32 | 33 | event.stopPropagation(); 34 | event.preventDefault(); 35 | 36 | if (enterAction) { 37 | enterAction(); 38 | } 39 | 40 | }); 41 | 42 | this.element.drop.addEventListener('dragleave', (event) => { 43 | 44 | event.stopPropagation(); 45 | event.preventDefault(); 46 | 47 | this.element.drop.classList.remove('drop-file-over'); 48 | 49 | if (leaveAction) { 50 | leaveAction(); 51 | } 52 | 53 | }); 54 | 55 | this.element.drop.addEventListener('dragover', (event) => { 56 | 57 | event.stopPropagation(); 58 | event.preventDefault(); 59 | 60 | this.element.drop.classList.add('drop-file-over'); 61 | 62 | }); 63 | 64 | this.element.drop.addEventListener('drop', (event) => { 65 | 66 | event.stopPropagation(); 67 | event.preventDefault(); 68 | 69 | this.element.drop.classList.remove('drop-file-over'); 70 | 71 | this.files = event.dataTransfer.files; 72 | 73 | if (dropAaction) { 74 | dropAaction(); 75 | } 76 | 77 | }); 78 | 79 | }; 80 | 81 | this.drop = () => { 82 | return this.element.drop; 83 | }; 84 | 85 | this.wrap = () => { 86 | return form.wrap({ 87 | children: [ 88 | this.element.drop 89 | ] 90 | }); 91 | }; 92 | 93 | this.assemble(); 94 | 95 | this.bind(); 96 | 97 | }; 98 | -------------------------------------------------------------------------------- /src/component/easterEgg/index.js: -------------------------------------------------------------------------------- 1 | import { data } from '../data'; 2 | import { menu } from '../menu'; 3 | import { bookmark } from '../bookmark'; 4 | 5 | import { StagedBookmark } from '../stagedBookmark'; 6 | 7 | import { randomNumber } from '../../utility/randomNumber'; 8 | import { convertColor } from '../../utility/convertColor'; 9 | 10 | const easterEgg = {}; 11 | 12 | easterEgg.toaster = {}; 13 | 14 | easterEgg.toaster.render = () => { 15 | 16 | easterEgg.toaster.bind.remove(); 17 | 18 | const newBookmarkData = new StagedBookmark(); 19 | 20 | newBookmarkData.link.url = 'https://en.wikipedia.org/wiki/Easter_egg_(media)'; 21 | 22 | newBookmarkData.link.background.show = true; 23 | 24 | newBookmarkData.link.background.image.url = 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1628494879270.gif?raw=true'; 25 | 26 | newBookmarkData.link.display.name.show = false; 27 | 28 | newBookmarkData.link.display.visual.show = false; 29 | 30 | newBookmarkData.link.accent.by = 'custom'; 31 | 32 | newBookmarkData.link.accent.hsl = { h: randomNumber(0, 360), s: 100, l: 50 }; 33 | 34 | newBookmarkData.link.accent.rgb = convertColor.hsl.rgb(newBookmarkData.link.accent.hsl); 35 | 36 | newBookmarkData.link.color.by = 'custom'; 37 | 38 | newBookmarkData.link.color.hsl = { h: 0, s: 0, l: 100 }; 39 | 40 | newBookmarkData.link.color.rgb = { r: 255, g: 255, b: 255 }; 41 | 42 | bookmark.item.mod.add(newBookmarkData); 43 | 44 | bookmark.item.clear(); 45 | 46 | bookmark.item.render(); 47 | 48 | menu.close(); 49 | 50 | data.save(); 51 | 52 | }; 53 | 54 | easterEgg.toaster.bind = { 55 | add: () => { 56 | 57 | menu.element.frame.element.area.addEventListener('animationend', easterEgg.toaster.render); 58 | 59 | menu.element.frame.element.area.classList.add('is-jello'); 60 | 61 | }, 62 | remove: () => { 63 | 64 | menu.element.frame.element.area.removeEventListener('animationend', easterEgg.toaster.render); 65 | 66 | menu.element.frame.element.area.classList.remove('is-jello'); 67 | 68 | } 69 | }; 70 | 71 | export { easterEgg }; 72 | -------------------------------------------------------------------------------- /src/component/form/feedback/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --form-feedback-space: 6; 3 | } 4 | 5 | :root { 6 | --form-feedback-background: var(--theme-primary-020); 7 | --form-feedback-background-disabled: var(--theme-primary-010); 8 | --form-feedback-text: var(--theme-primary-text-020); 9 | --form-feedback-text-muted: var(--theme-primary-070); 10 | --form-feedback-text-disabled: var(--theme-primary-030); 11 | --form-feedback-border: var(--theme-primary-030); 12 | --form-feedback-border-disabled: var(--theme-primary-010); 13 | } 14 | 15 | .form-feedback { 16 | background-color: hsl(var(--form-feedback-background)); 17 | padding: calc((var(--form-feedback-space) / 4) * 0.5em) calc((var(--form-feedback-space) / 4) * 1em); 18 | border: 0; 19 | border-left-width: calc(var(--layout-line-width) * 2); 20 | border-left-style: solid; 21 | border-left-color: hsl(var(--form-feedback-border)); 22 | border-top-right-radius: calc(var(--theme-radius) * 0.01em); 23 | border-bottom-right-radius: calc(var(--theme-radius) * 0.01em); 24 | width: 100%; 25 | transition: background-color var(--layout-transition-extra-fast), border-color var(--layout-transition-extra-fast); 26 | } 27 | 28 | .form-feedback p { 29 | color: hsl(var(--form-feedback-text)); 30 | } 31 | 32 | .form-feedback p.muted { 33 | color: hsl(var(--form-feedback-text-muted)); 34 | } 35 | 36 | .form-feedback.disabled { 37 | background-color: hsl(var(--form-feedback-background-disabled)); 38 | border-color: hsl(var(--form-feedback-border-disabled)); 39 | } 40 | 41 | .form-feedback.disabled p { 42 | color: hsl(var(--form-feedback-text-disabled)); 43 | } 44 | -------------------------------------------------------------------------------- /src/component/form/feedback/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | import { complexNode } from '../../../utility/complexNode'; 3 | 4 | import './index.css'; 5 | 6 | export const feedback = ({ 7 | text = false 8 | } = {}) => { 9 | 10 | const feedback = node('div|class:form-feedback'); 11 | 12 | if (text) { 13 | const feedbackText = complexNode({ 14 | tag: 'p', 15 | text: text, 16 | attr: [{ 17 | key: 'class', 18 | value: 'muted small' 19 | }] 20 | }); 21 | 22 | feedback.appendChild(feedbackText); 23 | } 24 | 25 | return feedback; 26 | 27 | }; 28 | -------------------------------------------------------------------------------- /src/component/form/fieldset/index.css: -------------------------------------------------------------------------------- 1 | .form-fieldset { 2 | position: relative; 3 | width: 100%; 4 | display: block; 5 | } 6 | -------------------------------------------------------------------------------- /src/component/form/fieldset/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const fieldset = function ({ 6 | children = false 7 | } = {}) { 8 | 9 | return node('fieldset|class:form-fieldset', children); 10 | 11 | }; -------------------------------------------------------------------------------- /src/component/form/grid/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const grid = ({ 6 | children = false 7 | } = {}) => { 8 | 9 | return node('div|class:form-grid', children); 10 | 11 | }; 12 | -------------------------------------------------------------------------------- /src/component/form/group/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const group = function ({ 6 | direction = 'horizontal', 7 | reverse = false, 8 | block = false, 9 | border = false, 10 | children = false, 11 | justify = 'left' 12 | } = {}) { 13 | 14 | const group = node('div|class:form-group', children); 15 | 16 | switch (direction) { 17 | case 'horizontal': 18 | group.classList.add('form-group-horizontal'); 19 | break; 20 | 21 | case 'vertical': 22 | group.classList.add('form-group-vertical'); 23 | break; 24 | } 25 | 26 | if (reverse) { 27 | group.classList.add('form-group-reverse'); 28 | } 29 | 30 | if (block) { 31 | group.classList.add('form-group-block'); 32 | } 33 | 34 | if (border) { 35 | group.classList.add('form-group-border'); 36 | } 37 | 38 | switch (justify) { 39 | 40 | case 'left': 41 | group.classList.add('form-group-justify-left'); 42 | break; 43 | 44 | case 'right': 45 | group.classList.add('form-group-justify-right'); 46 | break; 47 | 48 | case 'space-between': 49 | group.classList.add('form-group-justify-space-between'); 50 | break; 51 | 52 | } 53 | 54 | return group; 55 | 56 | }; 57 | -------------------------------------------------------------------------------- /src/component/form/groupText/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const groupText = ({ 6 | text = false, 7 | classList = [] 8 | } = {}) => { 9 | 10 | const textElement = node('div|class:form-group-text,tabindex:1'); 11 | 12 | if (text) { 13 | textElement.textContent = text; 14 | } 15 | 16 | if (classList.length > 0) { 17 | 18 | classList.forEach((item) => { 19 | textElement.classList.add(item); 20 | }); 21 | 22 | } 23 | 24 | return textElement; 25 | 26 | }; 27 | -------------------------------------------------------------------------------- /src/component/form/helper/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --form-helper: var(--theme-primary-140); 3 | --form-helper-disabled: var(--theme-primary-030); 4 | } 5 | 6 | .form-helper-item { 7 | font-size: 0.8em; 8 | color: hsl(var(--form-helper)); 9 | transition: color var(--layout-transition-extra-fast); 10 | } 11 | 12 | .form-helper-item.disabled { 13 | color: hsl(var(--form-helper-disabled)); 14 | } 15 | 16 | .form-helper-item.disabled a, 17 | .form-helper-item.disabled a:link, 18 | .form-helper-item.disabled a:visited, 19 | .form-helper-item.disabled a:focus, 20 | .form-helper-item.disabled a:hover, 21 | .form-helper-item.disabled a:active { 22 | color: hsl(var(--form-helper-disabled)); 23 | text-decoration: none; 24 | } 25 | -------------------------------------------------------------------------------- /src/component/form/helper/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const helper = function ({ 6 | text = 'text', 7 | complexText = false, 8 | classList = [] 9 | } = {}) { 10 | 11 | const helper = node('p|class:form-helper-item'); 12 | 13 | if (text) { 14 | 15 | if (complexText) { 16 | 17 | helper.innerHTML = text; 18 | 19 | } else { 20 | 21 | let textNode = document.createTextNode(text); 22 | 23 | helper.appendChild(textNode); 24 | 25 | } 26 | 27 | } 28 | 29 | if (classList.length > 0) { 30 | 31 | classList.forEach((item) => { 32 | helper.classList.add(item); 33 | }); 34 | 35 | } 36 | 37 | return helper; 38 | 39 | }; 40 | -------------------------------------------------------------------------------- /src/component/form/indent/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --indent-size: 6; 3 | --indent-space: calc((var(--indent-size) / 4) * 1em); 4 | } 5 | 6 | @media (min-width: 900px) { 7 | :root { 8 | --indent-size: 10; 9 | } 10 | } 11 | 12 | .form-indent { 13 | margin-left: var(--indent-space); 14 | } 15 | -------------------------------------------------------------------------------- /src/component/form/indent/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const indent = ({ 6 | children = false 7 | } = {}) => { 8 | 9 | return node('div|class:form-indent', children); 10 | 11 | }; 12 | -------------------------------------------------------------------------------- /src/component/form/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --form-space: 8; 3 | } 4 | 5 | :root { 6 | --form-placeholder: var(--theme-primary-040); 7 | --form-placeholder-focus-hover: var(--theme-primary-040); 8 | --form-placeholder-disabled: var(--theme-primary-020); 9 | } 10 | 11 | :root { 12 | --form-ring-hover: 0 0 0 var(--layout-line-width) hsl(var(--theme-primary-080)); 13 | --form-ring-focus: 14 | 0 0 0 var(--layout-line-width) hsl(var(--theme-primary-090)), 15 | 0 0 0 calc(var(--layout-line-width) * 2) hsla(var(--theme-primary-090), 0.25); 16 | --form-ring-accent: 0 0 0 var(--layout-line-width) rgb(var(--theme-accent)), 17 | 0 0 0 calc(var(--layout-line-width) * 2) rgba(var(--theme-accent), 0.25); 18 | } 19 | -------------------------------------------------------------------------------- /src/component/form/index.js: -------------------------------------------------------------------------------- 1 | import { feedback } from './feedback'; 2 | import { fieldset } from './fieldset'; 3 | import { group } from './group'; 4 | import { groupText } from './groupText'; 5 | import { helper } from './helper'; 6 | import { indent } from './indent'; 7 | import { inline } from './inline'; 8 | import { label } from './label'; 9 | import { sticky } from './sticky'; 10 | import { wrap } from './wrap'; 11 | import { grid } from './grid'; 12 | 13 | import * as input from './input'; 14 | 15 | import './index.css'; 16 | 17 | export { 18 | feedback, 19 | fieldset, 20 | grid, 21 | group, 22 | groupText, 23 | helper, 24 | indent, 25 | inline, 26 | label, 27 | sticky, 28 | wrap, 29 | input 30 | }; 31 | -------------------------------------------------------------------------------- /src/component/form/inline/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --form-inline-gap: 4; 3 | --form-inline-gap-small: calc(var(--form-inline-gap) * 1); 4 | --form-inline-gap-medium: calc(var(--form-inline-gap) * 2); 5 | --form-inline-gap-large: calc(var(--form-inline-gap) * 4); 6 | } 7 | 8 | .form-inline { 9 | position: relative; 10 | display: inline-flex; 11 | align-items: center; 12 | } 13 | 14 | .form-inline-justify-left { 15 | justify-content: flex-start; 16 | } 17 | 18 | .form-inline-justify-center { 19 | justify-content: center; 20 | } 21 | 22 | .form-inline-justify-right { 23 | justify-content: flex-end; 24 | } 25 | 26 | .form-inline-horizontal { 27 | flex-direction: row; 28 | } 29 | 30 | .form-inline-vertical { 31 | flex-direction: column; 32 | } 33 | 34 | .form-inline-gap-small { 35 | row-gap: calc((var(--form-inline-gap-small) / 12) * 1em); 36 | column-gap: calc((var(--form-inline-gap-small) / 4) * 1em); 37 | } 38 | 39 | .form-inline-gap-medium { 40 | row-gap: calc((var(--form-inline-gap-medium) / 12) * 1em); 41 | column-gap: calc((var(--form-inline-gap-medium) / 4) * 1em); 42 | } 43 | 44 | .form-inline-gap-large { 45 | row-gap: calc((var(--form-inline-gap-large) / 12) * 1em); 46 | column-gap: calc((var(--form-inline-gap-large) / 4) * 1em); 47 | } 48 | 49 | .form-inline-gap-equal.form-inline-gap-small { 50 | gap: calc((var(--form-inline-gap-small) / 4) * 1em); 51 | } 52 | 53 | .form-inline-gap-equal.form-inline-gap-medium { 54 | gap: calc((var(--form-inline-gap-medium) / 4) * 1em); 55 | } 56 | 57 | .form-inline-gap-equal.form-inline-gap-large { 58 | gap: calc((var(--form-inline-gap-large) / 4) * 1em); 59 | } 60 | 61 | .form-inline-wrap { 62 | flex-wrap: wrap; 63 | } 64 | 65 | .form-inline-block { 66 | display: flex; 67 | } 68 | 69 | .form-inline .form-wrap:not(:first-child), 70 | .form-inline .form-wrap:not(:last-child) { 71 | margin-top: 0; 72 | margin-bottom: 0; 73 | } 74 | 75 | .form-inline .form-wrap { 76 | flex-grow: 0; 77 | flex-shrink: 1; 78 | flex-basis: 0; 79 | } 80 | 81 | .form-inline .form-wrap label { 82 | white-space: nowrap; 83 | } 84 | 85 | .form-inline label:not(:only-child):not(:last-child) { 86 | padding-bottom: 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/component/form/inline/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const inline = function({ 6 | direction = 'horizontal', 7 | reverse = false, 8 | block = false, 9 | wrap = false, 10 | justify = 'left', 11 | gap = 'medium', 12 | equalGap = false, 13 | children = false 14 | } = {}) { 15 | 16 | const inline = node('div|class:form-inline', children); 17 | 18 | switch (direction) { 19 | case 'horizontal': 20 | inline.classList.add('form-inline-horizontal'); 21 | break; 22 | 23 | case 'vertical': 24 | inline.classList.add('form-inline-vertical'); 25 | break; 26 | } 27 | 28 | switch (gap) { 29 | 30 | case 'small': 31 | inline.classList.add('form-inline-gap-small'); 32 | break; 33 | 34 | case 'medium': 35 | inline.classList.add('form-inline-gap-medium'); 36 | break; 37 | 38 | case 'large': 39 | inline.classList.add('form-inline-gap-large'); 40 | break; 41 | 42 | } 43 | 44 | if (equalGap) { 45 | inline.classList.add('form-inline-gap-equal'); 46 | } 47 | 48 | switch (justify) { 49 | 50 | case 'left': 51 | inline.classList.add('form-inline-justify-left'); 52 | break; 53 | 54 | case 'center': 55 | inline.classList.add('form-inline-justify-center'); 56 | break; 57 | 58 | case 'right': 59 | inline.classList.add('form-inline-justify-right'); 60 | break; 61 | 62 | } 63 | 64 | if (reverse) { 65 | inline.classList.add('form-inline-reverse'); 66 | } 67 | 68 | if (block) { 69 | inline.classList.add('form-inline-block'); 70 | } 71 | 72 | if (wrap) { 73 | inline.classList.add('form-inline-wrap'); 74 | } 75 | 76 | return inline; 77 | 78 | }; 79 | -------------------------------------------------------------------------------- /src/component/form/input/checkbox/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const checkbox = ({ 6 | id = false, 7 | value = false, 8 | checked = false, 9 | classList = [], 10 | func = false 11 | } = {}) => { 12 | 13 | const input = node('input|type:checkbox,tabindex:1'); 14 | 15 | if (id) { 16 | input.setAttribute('id', id); 17 | } 18 | 19 | if (value) { 20 | input.setAttribute('value', value); 21 | } 22 | 23 | if (checked) { 24 | input.setAttribute('checked', ''); 25 | } 26 | 27 | if (classList.length > 0) { 28 | 29 | classList.forEach((item) => { 30 | input.classList.add(item); 31 | }); 32 | 33 | } 34 | 35 | if (func) { 36 | 37 | input.addEventListener('change', () => { 38 | func(); 39 | }); 40 | 41 | } 42 | 43 | return input; 44 | 45 | }; 46 | -------------------------------------------------------------------------------- /src/component/form/input/color/index.css: -------------------------------------------------------------------------------- 1 | input[type="color"] { 2 | background-color: transparent; 3 | padding: 0; 4 | margin: 0; 5 | width: 100%; 6 | min-width: 4em; 7 | height: 2.5em; 8 | display: block; 9 | border: 0; 10 | border-radius: calc(var(--theme-radius) * 0.01em); 11 | overflow: hidden; 12 | cursor: pointer; 13 | opacity: 1; 14 | transition: box-shadow var(--layout-transition-extra-fast), opacity var(--layout-transition-extra-fast); 15 | } 16 | 17 | input[type="color"]:hover { 18 | outline: none; 19 | box-shadow: var(--form-ring-hover); 20 | } 21 | 22 | input[type="color"]:focus { 23 | outline: none; 24 | box-shadow: var(--form-ring-focus); 25 | } 26 | 27 | input[type="color"]:disabled { 28 | opacity: 0.25; 29 | cursor: default; 30 | } 31 | 32 | input[type="color"]:disabled:hover, 33 | input[type="color"]:disabled:focus { 34 | box-shadow: none; 35 | } 36 | 37 | input[type="color"]::-webkit-color-swatch-wrapper { 38 | border: 0; 39 | padding: 0; 40 | outline: none; 41 | } 42 | 43 | input[type="color"]::-webkit-color-swatch { 44 | border: 0; 45 | padding: 0; 46 | outline: none; 47 | } 48 | 49 | input[type="color"]::-moz-color-swatch-wrapper { 50 | border: 0; 51 | padding: 0; 52 | outline: none; 53 | } 54 | 55 | input[type="color"]::-moz-color-swatch { 56 | border: 0; 57 | padding: 0; 58 | outline: none; 59 | } 60 | 61 | input[type="color"]::-moz-focus-inner { 62 | border: 0; 63 | padding: 0; 64 | outline: none; 65 | } 66 | 67 | .input-color-dot input[type="color"] { 68 | margin: 0; 69 | border-radius: 50%; 70 | position: absolute; 71 | top: 50%; 72 | right: 1em; 73 | width: var(--form-thumb); 74 | height: var(--form-thumb); 75 | min-width: inherit; 76 | z-index: 4; 77 | transform: translateY(-50%); 78 | transition: none; 79 | } 80 | 81 | .input-color-dot input[type="color"]:hover { 82 | outline: none; 83 | box-shadow: none; 84 | } 85 | 86 | .input-color-dot input[type="color"]:focus { 87 | outline: none; 88 | box-shadow: none; 89 | } 90 | 91 | .input-color-dot input[type="color"]+label { 92 | padding-right: calc(var(--form-thumb) + 2em); 93 | position: relative; 94 | } 95 | 96 | .input-color-dot.form-input-button-link input[type="color"] { 97 | box-shadow: 0 0 0 calc(var(--layout-line-width) * 0.75) hsl(var(--button-link-text)); 98 | transition: box-shadow var(--layout-transition-extra-fast); 99 | } 100 | -------------------------------------------------------------------------------- /src/component/form/input/color/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const color = function ({ 6 | id = false, 7 | value = '#000000', 8 | classList = [], 9 | func = false 10 | } = {}) { 11 | 12 | const input = node('input|type:color,value:' + value + ',tabindex:1'); 13 | 14 | if (id) { 15 | input.setAttribute('id', id); 16 | } 17 | 18 | if (classList.length > 0) { 19 | 20 | classList.forEach((item) => { 21 | input.classList.add(item); 22 | }); 23 | 24 | } 25 | 26 | if (func) { 27 | 28 | input.addEventListener('change', () => { 29 | func(); 30 | }); 31 | 32 | } 33 | 34 | return input; 35 | 36 | }; 37 | -------------------------------------------------------------------------------- /src/component/form/input/file/index.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/component/form/input/file/index.css -------------------------------------------------------------------------------- /src/component/form/input/file/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const file = ({ 6 | id = false, 7 | classList = [], 8 | func = false 9 | } = {}) => { 10 | 11 | const input = node('input|type:file,tabindex:1'); 12 | 13 | if (id) { 14 | input.setAttribute('id', id); 15 | } 16 | 17 | if (classList.length > 0) { 18 | 19 | classList.forEach((item) => { 20 | input.classList.add(item); 21 | }); 22 | 23 | } 24 | 25 | if (func) { 26 | 27 | input.addEventListener('change', () => { 28 | func(); 29 | }); 30 | 31 | } 32 | 33 | return input; 34 | 35 | }; 36 | -------------------------------------------------------------------------------- /src/component/form/input/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --form-thumb-size: 5; 3 | --form-thumb: calc((var(--form-thumb-size) / 4) * 1em); 4 | } 5 | 6 | :root { 7 | --form-input-background: var(--theme-primary-020); 8 | --form-input-background-hover: var(--theme-primary-020); 9 | --form-input-background-focus-active: var(--theme-primary-010); 10 | --form-input-background-disabled: var(--theme-primary-010); 11 | --form-input-text: var(--theme-primary-text-020); 12 | --form-input-text-hover: var(--theme-primary-text-020); 13 | --form-input-text-focus-active: var(--theme-primary-text-010); 14 | --form-input-text-disabled: var(--theme-primary-030); 15 | } 16 | 17 | :root { 18 | --form-icon: var(--theme-primary-060); 19 | --form-icon-hover: var(--theme-primary-040); 20 | --form-icon-focus: var(--theme-primary-040); 21 | --form-icon-active: var(--theme-primary-text-010); 22 | --form-icon-checked: var(--theme-primary-text-010); 23 | --form-icon-disabled: var(--theme-primary-020); 24 | } 25 | 26 | :root { 27 | --form-icon-symbol: var(--theme-primary-010); 28 | --form-icon-symbol-active: var(--theme-primary-010); 29 | --form-icon-symbol-disabled: var(--theme-primary-010); 30 | } 31 | -------------------------------------------------------------------------------- /src/component/form/input/index.js: -------------------------------------------------------------------------------- 1 | import { checkbox } from './checkbox'; 2 | import { color } from './color'; 3 | import { file } from './file'; 4 | import { number } from './number'; 5 | import { radio } from './radio'; 6 | import { range } from './range'; 7 | import { text } from './text'; 8 | import { textarea } from './textarea'; 9 | import { inputButton } from './inputButton'; 10 | import { select } from './select'; 11 | 12 | import './index.css'; 13 | 14 | export { 15 | checkbox, 16 | color, 17 | file, 18 | number, 19 | radio, 20 | range, 21 | text, 22 | textarea, 23 | inputButton, 24 | select 25 | }; 26 | -------------------------------------------------------------------------------- /src/component/form/input/inputButton/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const inputButton = function ({ 6 | children = false, 7 | inputHide = false, 8 | srOnly = false, 9 | style = [] 10 | } = {}) { 11 | 12 | const inputButtonElement = node('div|class:form-input-button', children); 13 | 14 | if (style.length > 0) { 15 | style.forEach((item) => { 16 | switch (item) { 17 | case 'link': 18 | inputButtonElement.classList.add('form-input-button-link'); 19 | break; 20 | 21 | case 'line': 22 | inputButtonElement.classList.add('form-input-button-line'); 23 | break; 24 | 25 | case 'ring': 26 | inputButtonElement.classList.add('form-input-button-ring'); 27 | break; 28 | 29 | case 'dot': 30 | inputButtonElement.classList.add('input-color-dot'); 31 | break; 32 | 33 | } 34 | }); 35 | } 36 | 37 | if (inputHide) { 38 | inputButtonElement.classList.add('form-input-hide'); 39 | } 40 | 41 | if (srOnly) { 42 | inputButtonElement.classList.add('form-input-button-sr-only'); 43 | } 44 | 45 | return inputButtonElement; 46 | 47 | }; 48 | -------------------------------------------------------------------------------- /src/component/form/input/number/index.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/component/form/input/number/index.css -------------------------------------------------------------------------------- /src/component/form/input/number/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const number = ({ 6 | id = false, 7 | min = 0, 8 | max = 100, 9 | step = 1, 10 | value = false, 11 | placeholder = false, 12 | classList = [], 13 | func = false 14 | } = {}) => { 15 | 16 | const input = node('input|type:number,min:' + min + ',max:' + max + ',step:' + step + ',tabindex:1'); 17 | 18 | if (id) { 19 | input.setAttribute('id', id); 20 | } 21 | 22 | if (value || (typeof value === 'number' && value === 0)) { 23 | input.setAttribute('value', value); 24 | } 25 | 26 | if (placeholder) { 27 | input.setAttribute('placeholder', placeholder); 28 | } 29 | 30 | if (classList.length > 0) { 31 | 32 | classList.forEach((item) => { 33 | input.classList.add(item); 34 | }); 35 | 36 | } 37 | 38 | if (func) { 39 | 40 | input.addEventListener('input', () => { 41 | func(); 42 | }); 43 | 44 | } 45 | 46 | return input; 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /src/component/form/input/radio/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const radio = function ({ 6 | id = false, 7 | radioGroup = false, 8 | value = false, 9 | checked = false, 10 | classList = [], 11 | func = false 12 | } = {}) { 13 | 14 | const input = node('input|type:radio,tabindex:1'); 15 | 16 | if (id) { 17 | input.setAttribute('id', id); 18 | } 19 | 20 | if (radioGroup) { 21 | input.setAttribute('name', radioGroup); 22 | } 23 | 24 | if (value) { 25 | input.setAttribute('value', value); 26 | } 27 | 28 | if (checked) { 29 | input.setAttribute('checked', ''); 30 | } 31 | 32 | if (classList.length > 0) { 33 | 34 | classList.forEach((item) => { 35 | input.classList.add(item); 36 | }); 37 | 38 | } 39 | 40 | if (func) { 41 | input.addEventListener('change', () => { 42 | func(); 43 | }); 44 | } 45 | 46 | return input; 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /src/component/form/input/range/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const range = ({ 6 | id = false, 7 | min = 0, 8 | max = 100, 9 | step = 1, 10 | value = 0, 11 | classList = [], 12 | func = false, 13 | focusFunc = false, 14 | blurFunc = false, 15 | mouseDownFunc = false, 16 | mouseUpFunc = false 17 | } = {}) => { 18 | 19 | const input = node('input|type:range,min:' + min + ',max:' + max + ',step:' + step + ',value:' + value + ',tabindex:1'); 20 | 21 | if (id) { 22 | input.setAttribute('id', id); 23 | } 24 | 25 | if (classList.length > 0) { 26 | 27 | classList.forEach((item) => { 28 | input.classList.add(item); 29 | }); 30 | 31 | } 32 | 33 | if (func) { 34 | 35 | input.addEventListener('input', () => { 36 | func(); 37 | }); 38 | 39 | } 40 | 41 | if (focusFunc) { 42 | 43 | input.addEventListener('focus', () => { 44 | focusFunc(); 45 | }); 46 | 47 | } 48 | 49 | if (blurFunc) { 50 | 51 | input.addEventListener('blur', () => { 52 | blurFunc(); 53 | }); 54 | 55 | } 56 | 57 | if (mouseDownFunc) { 58 | 59 | input.addEventListener('mousedown', () => { 60 | mouseDownFunc(); 61 | }); 62 | 63 | } 64 | 65 | if (mouseUpFunc) { 66 | 67 | input.addEventListener('mouseup', () => { 68 | mouseUpFunc(); 69 | }); 70 | 71 | } 72 | 73 | return input; 74 | 75 | }; 76 | -------------------------------------------------------------------------------- /src/component/form/input/select/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | import { complexNode } from '../../../../utility/complexNode'; 3 | import { trimString } from '../../../../utility/trimString'; 4 | 5 | import './index.css'; 6 | 7 | export const select = function({ 8 | id = false, 9 | classList = [], 10 | option = [], 11 | selected = 0, 12 | func = false 13 | } = {}) { 14 | 15 | const select = node('select|tabindex:1'); 16 | 17 | if (id) { 18 | select.setAttribute('id', id); 19 | } 20 | 21 | if (classList.length > 0) { 22 | 23 | classList.forEach((item) => { 24 | select.classList.add(item); 25 | }); 26 | 27 | } 28 | 29 | if (func) { 30 | 31 | select.addEventListener('change', () => { 32 | func(); 33 | }); 34 | 35 | } 36 | 37 | if (option.length > 0) { 38 | option.forEach((item) => { 39 | 40 | if (typeof item == 'string') { 41 | 42 | select.appendChild( 43 | complexNode({ 44 | tag: 'option', 45 | text: item, 46 | attr: [{ 47 | key: 'value', 48 | value: trimString(item).replace(/\s+/g, '-').toLowerCase() 49 | }] 50 | }) 51 | ); 52 | 53 | } else { 54 | 55 | const option = complexNode({ tag: 'option' }); 56 | 57 | if (item.name) { 58 | option.textContent = item.name; 59 | } 60 | 61 | if (item.id) { 62 | option.value = item.id; 63 | } 64 | 65 | if (item.disabled) { 66 | option.disabled = true; 67 | } 68 | 69 | select.appendChild(option); 70 | 71 | } 72 | 73 | }); 74 | } 75 | 76 | select.selectedIndex = selected; 77 | 78 | return select; 79 | 80 | }; 81 | -------------------------------------------------------------------------------- /src/component/form/input/text/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const text = ({ 6 | id = false, 7 | value = false, 8 | min = false, 9 | max = false, 10 | placeholder = false, 11 | classList = [], 12 | func = false 13 | } = {}) => { 14 | 15 | const input = node('input|type:text,autocomplete:off,autocorrect:off,autocapitalize:off,spellcheck:false,tabindex:1'); 16 | 17 | if (id) { 18 | input.setAttribute('id', id); 19 | } 20 | 21 | if (value) { 22 | input.setAttribute('value', value); 23 | } 24 | 25 | if (typeof min === 'number') { 26 | input.setAttribute('minlength', min); 27 | } 28 | 29 | if (typeof max === 'number') { 30 | input.setAttribute('maxlength', max); 31 | } 32 | 33 | if (placeholder) { 34 | input.setAttribute('placeholder', placeholder); 35 | } 36 | 37 | if (classList.length > 0) { 38 | 39 | classList.forEach((item) => { 40 | input.classList.add(item); 41 | }); 42 | 43 | } 44 | 45 | if (func) { 46 | 47 | input.addEventListener('input', () => { 48 | func(); 49 | }); 50 | 51 | } 52 | 53 | return input; 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /src/component/form/input/textarea/index.css: -------------------------------------------------------------------------------- 1 | textarea { 2 | background-color: hsl(var(--form-input-background)); 3 | padding: 0.5em 1.25em; 4 | margin: 0; 5 | color: hsl(var(--form-input-text)); 6 | font-size: 1em; 7 | line-height: 1.6; 8 | font-family: var(--theme-font-ui-name); 9 | font-weight: var(--theme-font-ui-weight); 10 | font-style: var(--theme-font-ui-style); 11 | height: 10em; 12 | min-height: 2.5em; 13 | min-width: 0; 14 | width: 100%; 15 | border-width: 0; 16 | border-radius: calc(var(--theme-radius) * 0.01em); 17 | cursor: text; 18 | resize: vertical; 19 | display: block; 20 | transition: background-color var(--layout-transition-extra-fast), border-color var(--layout-transition-extra-fast), color var(--layout-transition-extra-fast), box-shadow var(--layout-transition-extra-fast); 21 | -moz-appearance: textfield; 22 | } 23 | 24 | textarea:hover { 25 | background-color: hsl(var(--form-input-background-hover)); 26 | color: hsl(var(--form-input-text-hover)); 27 | outline: none; 28 | box-shadow: var(--form-ring-hover); 29 | } 30 | 31 | textarea:focus, 32 | textarea:active { 33 | background-color: hsl(var(--form-input-background-focus-active)); 34 | color: hsl(var(--form-input-text-focus-active)); 35 | outline: none; 36 | box-shadow: var(--form-ring-accent); 37 | } 38 | 39 | textarea:disabled { 40 | background-color: hsl(var(--form-input-background-disabled)); 41 | color: hsl(var(--form-input-text-disabled)); 42 | cursor: default; 43 | box-shadow: none; 44 | resize: none; 45 | } 46 | 47 | textarea:disabled:hover, 48 | textarea:disabled:focus { 49 | color: hsl(var(--form-input-text-disabled)); 50 | } 51 | 52 | textarea::placeholder { 53 | color: hsl(var(--form-placeholder)); 54 | transition: color var(--layout-transition-extra-fast); 55 | } 56 | 57 | textarea:hover::placeholder { 58 | color: hsl(var(--form-placeholder-focus-hover)); 59 | } 60 | 61 | textarea:focus::placeholder { 62 | color: hsl(var(--form-placeholder-focus-hover)); 63 | } 64 | 65 | textarea:disabled::placeholder, 66 | textarea:disabled:hover::placeholder, 67 | textarea:disabled:focus::placeholder { 68 | color: hsl(var(--form-placeholder-disabled)); 69 | } 70 | -------------------------------------------------------------------------------- /src/component/form/input/textarea/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const textarea = function ({ 6 | id = false, 7 | value = false, 8 | placeholder = false, 9 | classList = [], 10 | func = false 11 | } = {}) { 12 | 13 | const textarea = node('textarea|tabindex:1,spellcheck:false'); 14 | 15 | if (id) { 16 | textarea.setAttribute('id', id); 17 | } 18 | 19 | if (value) { 20 | textarea.setAttribute('value', value); 21 | } 22 | 23 | if (placeholder) { 24 | textarea.setAttribute('placeholder', placeholder); 25 | } 26 | 27 | if (classList.length > 0) { 28 | 29 | classList.forEach((item) => { 30 | textarea.classList.add(item); 31 | }); 32 | 33 | } 34 | 35 | if (func) { 36 | 37 | textarea.addEventListener('input', () => { 38 | func(); 39 | }); 40 | 41 | } 42 | 43 | return textarea; 44 | 45 | }; 46 | -------------------------------------------------------------------------------- /src/component/form/label/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --form-label: var(--theme-primary-text-010); 3 | --form-label-hover: var(--theme-primary-text-010); 4 | --form-label-focus-active: var(--theme-primary-text-010); 5 | --form-label-checked: var(--theme-primary-text-010); 6 | --form-label-disabled: var(--theme-primary-030); 7 | } 8 | 9 | label { 10 | padding: 0; 11 | color: hsl(var(--form-label)); 12 | margin-bottom: 0; 13 | font-size: 1em; 14 | display: block; 15 | transition: color var(--layout-transition-extra-fast); 16 | } 17 | 18 | label:not(.label-no-padding):not(:only-child):not(:last-child) { 19 | padding-bottom: 1em; 20 | } 21 | 22 | label.disabled { 23 | color: hsl(var(--form-label-disabled)); 24 | } 25 | 26 | .label-block { 27 | display: flex; 28 | flex-direction: column; 29 | flex-wrap: nowrap; 30 | gap: 0.25em; 31 | } 32 | 33 | input:disabled+label .label-block-item, 34 | input:disabled:hover+label .label-block-item, 35 | input:disabled:focus+label .label-block-item { 36 | color: hsl(var(--form-label-disabled)); 37 | cursor: default; 38 | } 39 | -------------------------------------------------------------------------------- /src/component/form/label/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const label = ({ 6 | forInput = false, 7 | text = 'label', 8 | description = false, 9 | srOnly = false, 10 | icon = false, 11 | noPadding = false, 12 | classList = [] 13 | } = {}) => { 14 | 15 | let label; 16 | 17 | if (forInput) { 18 | label = node('label|for:' + forInput); 19 | } else { 20 | label = node('label'); 21 | } 22 | 23 | if (noPadding) { 24 | label.classList.add('label-no-padding'); 25 | } 26 | 27 | const labelBlock = node('span|class:label-block'); 28 | 29 | if (srOnly) { 30 | if (icon) { 31 | labelBlock.classList.add('sr-only'); 32 | } else { 33 | label.classList.add('sr-only'); 34 | } 35 | } 36 | 37 | if (text) { 38 | labelBlock.appendChild(node('span:' + text + '|class:label-block-item')); 39 | } 40 | 41 | if (description) { 42 | if (Array.isArray(description)) { 43 | 44 | description.forEach((item) => { 45 | labelBlock.appendChild(node('span:' + item + '|class:label-block-item small muted')); 46 | }); 47 | 48 | } else if (typeof description === 'string') { 49 | 50 | labelBlock.appendChild(node('span:' + description + '|class:label-block-item small muted')); 51 | 52 | } 53 | } 54 | 55 | if (text || description) { 56 | label.appendChild(labelBlock); 57 | } 58 | 59 | if (icon) { 60 | label.prepend(node('span|class:label-icon')); 61 | } 62 | 63 | if (classList.length > 0) { 64 | 65 | classList.forEach((item) => { 66 | label.classList.add(item); 67 | }); 68 | 69 | } 70 | 71 | return label; 72 | 73 | }; 74 | -------------------------------------------------------------------------------- /src/component/form/sticky/index.css: -------------------------------------------------------------------------------- 1 | .form-sticky { 2 | background-color: hsl(var(--theme-primary-010)); 3 | margin: -1em; 4 | padding: 1em; 5 | position: sticky; 6 | top: 0; 7 | z-index: 4; 8 | transition: background-color var(--layout-transition-extra-fast); 9 | } 10 | -------------------------------------------------------------------------------- /src/component/form/sticky/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const sticky = function ({ 6 | children = false 7 | } = {}) { 8 | 9 | return node('div|class:form-sticky', children); 10 | 11 | }; -------------------------------------------------------------------------------- /src/component/form/wrap/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --wrap-size: 6; 3 | --wrap-space: calc((var(--wrap-size) / 4) * 1em); 4 | } 5 | 6 | .form-wrap { 7 | position: relative; 8 | width: 100%; 9 | display: block; 10 | } 11 | 12 | .form-wrap:not(:first-child) { 13 | margin-top: var(--wrap-space); 14 | } 15 | 16 | .form-wrap:not(:last-child) { 17 | margin-bottom: var(--wrap-space); 18 | } 19 | -------------------------------------------------------------------------------- /src/component/form/wrap/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | export const wrap = ({ 6 | children = false 7 | } = {}) => { 8 | 9 | return node('div|class:form-wrap', children); 10 | 11 | }; 12 | -------------------------------------------------------------------------------- /src/component/grid/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --grid-cell-size: calc(var(--bookmark-size) - calc(var(--grid-gap) / 5)); 3 | } 4 | 5 | .grid-area { 6 | perspective: calc(var(--grid-perspective) * 1em); 7 | font-size: calc(var(--grid-size) * 0.01rem); 8 | position: relative; 9 | right: 0; 10 | transition: right var(--layout-transition-extra-fast); 11 | } 12 | 13 | .grid-list { 14 | position: relative; 15 | display: grid; 16 | grid-template-columns: repeat(var(--grid-column), calc(calc(var(--grid-cell-size) / 2) * 0.1em) calc(var(--grid-cell-size) * 0.1em)) calc(calc(var(--grid-cell-size) / 2) * 0.1em); 17 | grid-gap: calc(var(--grid-gap) * 0.01em) calc(calc(var(--grid-gap) * 2) * 0.01em); 18 | transform: rotateX(calc(var(--grid-transform-rotate-x) * 1deg)) rotateY(calc(var(--grid-transform-rotate-y) * 1deg)) rotateZ(calc(var(--grid-transform-rotate-z) * 1deg)); 19 | transition: transform var(--layout-transition-medium); 20 | transform-style: preserve-3d; 21 | transform-origin: center; 22 | } 23 | 24 | .is-bookmark-edit .grid-list { 25 | transform: rotateX(0) rotateY(0) rotateZ(0); 26 | } 27 | 28 | @media (min-width: 1200px) { 29 | .is-menu-open .grid-area { 30 | right: 20vw; 31 | transition: right var(--layout-transition-extra-fast) var(--layout-duration-02); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/component/icon/index.css: -------------------------------------------------------------------------------- 1 | .icon { 2 | width: 1em; 3 | height: 1em; 4 | font-size: 1.5em; 5 | display: flex; 6 | } 7 | 8 | .icon svg { 9 | width: 100%; 10 | height: 100%; 11 | fill: currentColor; 12 | vertical-align: middle; 13 | overflow: hidden; 14 | display: block; 15 | } 16 | -------------------------------------------------------------------------------- /src/component/index.js: -------------------------------------------------------------------------------- 1 | import { base } from './base'; 2 | import { body } from './body'; 3 | import { state } from './state'; 4 | import { data } from './data'; 5 | import { version } from './version'; 6 | import { fontawesome } from './fontawesome'; 7 | import { grid } from './grid'; 8 | import { icon } from './icon'; 9 | import { keyboard } from './keyboard'; 10 | import { layout } from './layout'; 11 | import { menu } from './menu'; 12 | import { pageLock } from './pageLock'; 13 | import { theme } from './theme'; 14 | import { toolbar } from './toolbar'; 15 | import { update } from './update'; 16 | import { bookmark } from './bookmark'; 17 | 18 | import * as form from './form'; 19 | 20 | export const component = { 21 | base, 22 | body, 23 | state, 24 | data, 25 | version, 26 | fontawesome, 27 | grid, 28 | icon, 29 | keyboard, 30 | layout, 31 | menu, 32 | pageLock, 33 | theme, 34 | toolbar, 35 | update, 36 | bookmark, 37 | form 38 | }; 39 | -------------------------------------------------------------------------------- /src/component/keyboardShortcut/index.js: -------------------------------------------------------------------------------- 1 | export const KeyboardShortcut = function({ 2 | keycode = false, 3 | ctrl = false, 4 | alt = false, 5 | action = false 6 | } = {}) { 7 | 8 | this.action = () => { 9 | if (keycode) { 10 | if ((event.keyCode == keycode) && (ctrl == event.ctrlKey) && (alt == event.altKey)) { 11 | 12 | event.preventDefault(); 13 | 14 | if (action) { 15 | action(); 16 | } 17 | 18 | } 19 | } 20 | }; 21 | 22 | this.add = () => { window.addEventListener('keydown', this.action); }; 23 | 24 | this.remove = () => { window.removeEventListener('keydown', this.action); }; 25 | 26 | }; 27 | -------------------------------------------------------------------------------- /src/component/layout/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --layout-size: 1; 3 | } 4 | 5 | :root { 6 | --layout-line-width: 0.25em; 7 | } 8 | 9 | :root { 10 | --layout-duration-01: 0.1s; 11 | --layout-duration-02: 0.2s; 12 | --layout-duration-03: 0.3s; 13 | --layout-duration-04: 0.4s; 14 | --layout-duration-05: 0.5s; 15 | --layout-duration-06: 0.6s; 16 | --layout-duration-07: 0.7s; 17 | --layout-duration-08: 0.8s; 18 | --layout-duration-09: 0.9s; 19 | --layout-duration-10: 1s; 20 | --layout-timing-ease: ease-in-out; 21 | --layout-timing-bounce: cubic-bezier(0.8, 0.8, 0.4, 1.4); 22 | --layout-transition-extra-fast: var(--layout-duration-02) var(--layout-timing-ease); 23 | --layout-transition-fast: var(--layout-duration-04) var(--layout-timing-ease); 24 | --layout-transition-medium: var(--layout-duration-06) var(--layout-timing-ease); 25 | --layout-transition-slow: var(--layout-duration-08) var(--layout-timing-ease); 26 | --layout-transition-extra-slow: var(--layout-duration-10) var(--layout-timing-ease); 27 | } 28 | 29 | :root { 30 | --layout-horizontal-rule-small: 1px solid hsl(var(--theme-primary-020)); 31 | --layout-horizontal-rule-large: 2px solid hsl(var(--theme-primary-020)); 32 | } 33 | 34 | .layout { 35 | z-index: var(--z-index-layout); 36 | } 37 | 38 | .layout-area { 39 | display: grid; 40 | align-items: center; 41 | justify-content: center; 42 | margin: calc(var(--grid-gap) * 0.01em); 43 | } 44 | -------------------------------------------------------------------------------- /src/component/layout/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | const layout = {}; 6 | 7 | layout.element = { 8 | layout: node('div|class:layout'), 9 | area: node('div|class:layout-area') 10 | }; 11 | 12 | layout.area = { 13 | render: () => { 14 | 15 | layout.element.layout.appendChild(layout.element.area); 16 | 17 | document.querySelector('body').appendChild(layout.element.layout); 18 | 19 | } 20 | }; 21 | 22 | layout.init = () => { 23 | layout.area.render(); 24 | }; 25 | 26 | export { layout }; 27 | -------------------------------------------------------------------------------- /src/component/logo/index.js: -------------------------------------------------------------------------------- 1 | import { easterEgg } from '../easterEgg'; 2 | 3 | import { node } from '../../utility/node'; 4 | 5 | import './index.css'; 6 | 7 | export const Logo = function() { 8 | 9 | this.element = { 10 | logo: node('div|class:logo'), 11 | svg: '' 16 | }; 17 | 18 | this.assemble = () => { 19 | 20 | this.element.logo.innerHTML = this.element.svg; 21 | 22 | }; 23 | 24 | this.bind = () => { 25 | 26 | this.element.logo.addEventListener('dblclick', () => { easterEgg.toaster.bind.add(); }); 27 | 28 | }; 29 | 30 | this.logo = () => { 31 | return this.element.logo; 32 | }; 33 | 34 | this.assemble(); 35 | 36 | this.bind(); 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /src/component/menu/index.js: -------------------------------------------------------------------------------- 1 | import { state } from '../state'; 2 | import { APP_NAME } from '../../constant'; 3 | 4 | import { MenuFrame } from '../menuFrame'; 5 | 6 | const menu = {}; 7 | 8 | menu.navData = [ 9 | // { name: 'Debug', id: 'debug', active: true, overscroll: true, sub: ['Input', 'Button', 'Bookmark', 'Icon'] }, 10 | { name: 'Theme', id: 'theme', active: true, overscroll: true, sub: ['Preset', 'Saved', 'Style', 'Colour', 'Accent', 'Font', 'Shade', 'Opacity', 'Background', 'Bookmark'] }, 11 | { name: 'Layout', id: 'layout', active: false, overscroll: true, sub: ['Scaling', 'Grid'] }, 12 | { name: 'Bookmark', id: 'bookmark', active: false, overscroll: true, sub: ['General', 'Hover', 'Shadow'] }, 13 | { name: 'Toolbar', id: 'toolbar', active: false, overscroll: true, sub: ['Size', 'Position', 'Controls'] }, 14 | { name: 'Data', id: 'data', active: false, overscroll: true, sub: ['Restore', 'Backup', 'Clear'] }, 15 | { name: 'Support', id: 'support', active: false, overscroll: false }, 16 | { name: 'Coffee', id: 'coffee', active: false, overscroll: false }, 17 | { name: APP_NAME, id: 'app', active: false, overscroll: false } 18 | ]; 19 | 20 | menu.mod = {}; 21 | 22 | menu.element = { 23 | frame: null 24 | }; 25 | 26 | menu.open = (name) => { 27 | 28 | menu.element.frame = new MenuFrame({ 29 | navData: menu.navData 30 | }); 31 | 32 | if (name) { 33 | 34 | menu.element.frame.menuNav.state.toggle(name); 35 | 36 | } 37 | 38 | menu.element.frame.open(); 39 | 40 | }; 41 | 42 | menu.close = () => { 43 | 44 | if (menu.element.frame) { 45 | menu.element.frame.close(); 46 | } 47 | 48 | }; 49 | 50 | menu.toggle = () => { 51 | 52 | if (state.get.current().menu) { 53 | menu.close(); 54 | } else { 55 | menu.open(); 56 | } 57 | 58 | }; 59 | 60 | export { menu }; 61 | -------------------------------------------------------------------------------- /src/component/menuClose/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --menu-close-size: 12; 3 | --menu-close-space: calc((var(--menu-close-size) / 4) * 1em); 4 | } 5 | 6 | @media (min-width: 700px) { 7 | :root { 8 | --menu-close-size: 14; 9 | } 10 | } 11 | 12 | .menu-close { 13 | grid-column-start: 3; 14 | grid-column-end: 4; 15 | grid-row-start: 1; 16 | grid-row-end: 2; 17 | align-self: start; 18 | z-index: 3; 19 | } 20 | 21 | .menu-close-button { 22 | background-color: transparent; 23 | margin: 0; 24 | padding: 0; 25 | border-radius: 0; 26 | line-height: 1; 27 | position: relative; 28 | top: calc((var(--theme-radius) * 0.25) * 0.01em); 29 | right: calc((var(--theme-radius) * 0.25) * 0.01em); 30 | height: var(--menu-close-space); 31 | width: var(--menu-close-space); 32 | } 33 | 34 | @media (min-width: 700px) { 35 | .menu-close-button { 36 | border-radius: calc(var(--theme-radius) * 0.01em); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/component/menuClose/index.js: -------------------------------------------------------------------------------- 1 | import { menu } from '../menu'; 2 | 3 | import { Button } from '../button'; 4 | 5 | import { node } from '../../utility/node'; 6 | 7 | import './index.css'; 8 | 9 | export const MenuClose = function() { 10 | 11 | this.element = { 12 | close: node('div|class:menu-close') 13 | }; 14 | 15 | this.button = new Button({ 16 | text: 'Close settings menu', 17 | srOnly: true, 18 | style: ['link'], 19 | iconName: 'cross', 20 | classList: ['menu-close-button'], 21 | func: () => { 22 | menu.close(); 23 | } 24 | }); 25 | 26 | this.assemble = () => { 27 | 28 | this.element.close.appendChild(this.button.button); 29 | 30 | }; 31 | 32 | this.close = () => { 33 | 34 | return this.element.close; 35 | 36 | }; 37 | 38 | this.assemble(); 39 | 40 | }; 41 | -------------------------------------------------------------------------------- /src/component/menuContent/appSetting/index.js: -------------------------------------------------------------------------------- 1 | import * as form from '../../form'; 2 | 3 | import { node } from '../../../utility/node'; 4 | 5 | import { APP_NAME } from '../../../constant'; 6 | 7 | import { Link } from '../../link'; 8 | import { Splash } from '../../splash'; 9 | 10 | const appSetting = {}; 11 | 12 | appSetting.app = (parent) => { 13 | 14 | appSetting.app.para = node('p:This project is open source.'); 15 | 16 | appSetting.app.link1 = new Link({ 17 | text: 'Found on GitHub.', 18 | href: `https://github.com/zombieFox/${APP_NAME}`, 19 | openNew: true 20 | }); 21 | 22 | appSetting.app.link2 = new Link({ 23 | text: 'GNU General Public Licence v3.0.', 24 | href: `https://github.com/zombieFox/${APP_NAME}/blob/master/license`, 25 | openNew: true 26 | }); 27 | 28 | const splash = new Splash(); 29 | 30 | parent.appendChild( 31 | node('div', [ 32 | splash.splash(), 33 | node('hr'), 34 | form.wrap({ 35 | children: [ 36 | appSetting.app.para, 37 | form.indent({ 38 | children: [ 39 | node('p', [ 40 | appSetting.app.link1.link() 41 | ]), 42 | node('p', [ 43 | appSetting.app.link2.link() 44 | ]) 45 | ] 46 | }) 47 | ] 48 | }) 49 | ]) 50 | ); 51 | 52 | }; 53 | 54 | export { appSetting }; 55 | -------------------------------------------------------------------------------- /src/component/menuContent/coffeeSetting/index.js: -------------------------------------------------------------------------------- 1 | import { APP_NAME } from '../../../constant'; 2 | 3 | import * as form from '../../form'; 4 | 5 | import { Link } from '../../link'; 6 | 7 | 8 | import { node } from '../../../utility/node'; 9 | import { complexNode } from '../../../utility/complexNode'; 10 | 11 | const coffeeSetting = {}; 12 | 13 | coffeeSetting.coffee = (parent) => { 14 | 15 | parent.appendChild( 16 | node('div', [ 17 | complexNode({ 18 | tag: 'p', 19 | text: APP_NAME + ' is free, appreciation is welcome in the form of coffee!' 20 | }), 21 | form.wrap({ 22 | children: [(new Link({ 23 | text: 'Buy me a coffee', 24 | href: 'https://www.buymeacoffee.com/zombieFox', 25 | iconName: 'coffee', 26 | iconPosition: 'left', 27 | linkButton: true, 28 | openNew: true, 29 | style: ['line'], 30 | classList: ['button-line', 'button-extra-large'] 31 | })).link()] 32 | }) 33 | ]) 34 | ); 35 | 36 | }; 37 | 38 | export { coffeeSetting }; 39 | -------------------------------------------------------------------------------- /src/component/menuContent/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --menu-content-space: 12; 3 | } 4 | 5 | .menu-content { 6 | grid-column-start: 1; 7 | grid-column-end: 4; 8 | } 9 | 10 | @media (min-width: 700px) { 11 | .menu-content { 12 | grid-column-start: 2; 13 | grid-column-end: 4; 14 | grid-row-start: 1; 15 | grid-row-end: 1; 16 | overflow-y: auto; 17 | } 18 | } 19 | 20 | @media (min-width: 900px) { 21 | :root { 22 | --menu-content-space: 20; 23 | } 24 | 25 | .menu-content { 26 | grid-column-start: 2; 27 | grid-column-end: 4; 28 | grid-row-start: 1; 29 | grid-row-end: 2; 30 | scroll-behavior: smooth; 31 | overflow-y: auto; 32 | z-index: 2; 33 | } 34 | } 35 | 36 | .menu-content-item { 37 | padding-top: calc((var(--menu-content-space) / 4) * 1em); 38 | padding-right: calc((var(--menu-content-space) / 4) * 1em); 39 | padding-left: calc((var(--menu-content-space) / 4) * 1em); 40 | position: relative; 41 | z-index: 1; 42 | } 43 | 44 | .menu-content-item:last-child { 45 | padding-bottom: calc((var(--menu-content-space) / 4) * 1em); 46 | } 47 | 48 | .menu-content-overscroll .menu-content-item:last-child { 49 | padding-bottom: calc((var(--menu-content-space) * 2) * 1em); 50 | } 51 | 52 | .menu-item-header { 53 | padding-bottom: calc((var(--menu-content-space) / 8) * 1em); 54 | } 55 | 56 | .menu-item-header-text { 57 | margin-bottom: 0; 58 | } 59 | 60 | .menu-item-form { 61 | z-index: 1; 62 | } 63 | 64 | .menu-item-form-indent { 65 | margin-left: calc((var(--menu-content-space) / 8) * 1em); 66 | } 67 | -------------------------------------------------------------------------------- /src/component/menuContent/supportSetting/index.js: -------------------------------------------------------------------------------- 1 | import { APP_NAME } from '../../../constant'; 2 | 3 | import * as form from '../../form'; 4 | 5 | import { Link } from '../../link'; 6 | 7 | 8 | import { node } from '../../../utility/node'; 9 | 10 | const supportSetting = {}; 11 | 12 | supportSetting.link = { 13 | url: 'https://github.com/zombieFox/' + APP_NAME + '/wiki/', 14 | page: { 15 | applyToAll: 'Applying-bookmark-settings-to-all', 16 | browser: 'Browser-support', 17 | cookies: 'Cookies-and-cache', 18 | data: 'Data-backup-and-restore', 19 | protectedUrl: 'Protected-URLs', 20 | recovering: 'Recovering-settings-and-bookmarks', 21 | resetting: 'Resetting-when-opening-the-browser', 22 | privacy: 'Respecting-your-privacy', 23 | backgroundImageVideo: 'Setting-a-background-video-or-image', 24 | firefox: 'Setting-' + APP_NAME + '-as-your-Firefox-homepage' 25 | } 26 | }; 27 | 28 | supportSetting.support = (parent) => { 29 | 30 | const makeLinks = () => { 31 | 32 | const wrap = form.wrap(); 33 | 34 | const list = node('ul|class:list-feature'); 35 | 36 | for (var key in supportSetting.link.page) { 37 | 38 | const supportLink = new Link({ 39 | text: supportSetting.link.page[key].replace(/-/g, ' '), 40 | href: supportSetting.link.url + supportSetting.link.page[key], 41 | openNew: true 42 | }); 43 | 44 | list.appendChild(node('li', [supportLink.link()])); 45 | 46 | } 47 | 48 | wrap.appendChild(list); 49 | 50 | return wrap; 51 | 52 | }; 53 | 54 | const para = node('p'); 55 | 56 | para.innerHTML = `For more support or feedback, submit an ${(new Link({ text:'Issue', href: `https://github.com/zombieFox/${APP_NAME}/issues`, openNew: true })).link().outerHTML} or check the ${(new Link({ text:'Wiki', href: `https://github.com/zombieFox/${APP_NAME}/wiki`, openNew: true })).link().outerHTML}.`; 57 | 58 | parent.appendChild( 59 | node('div', [ 60 | makeLinks(), 61 | node('hr'), 62 | para 63 | ]) 64 | ); 65 | 66 | }; 67 | 68 | export { supportSetting }; 69 | -------------------------------------------------------------------------------- /src/component/menuFrame/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --menu-background: var(--theme-primary-010); 3 | --menu-text: var(--theme-primary-text-010); 4 | } 5 | 6 | .menu { 7 | padding: 1em; 8 | position: fixed; 9 | top: 0; 10 | right: 0; 11 | width: 100vw; 12 | height: 90vh; 13 | opacity: 0; 14 | z-index: var(--z-index-menu); 15 | pointer-events: none; 16 | transition: opacity var(--layout-transition-extra-fast); 17 | } 18 | 19 | @media (min-width: 550px) { 20 | .menu { 21 | width: 90vw; 22 | } 23 | } 24 | 25 | @media (min-width: 700px) { 26 | .menu { 27 | width: 100%; 28 | height: 100%; 29 | max-height: initial; 30 | } 31 | } 32 | 33 | @media (min-width: 900px) { 34 | .menu { 35 | width: 90vw; 36 | } 37 | } 38 | 39 | @media (min-width: 1100px) { 40 | .menu { 41 | width: 80vw; 42 | max-width: 60em; 43 | } 44 | } 45 | 46 | .menu-area { 47 | background-color: hsl(var(--menu-background)); 48 | border-radius: calc(var(--theme-radius) * 0.01em); 49 | width: 100%; 50 | max-height: 100%; 51 | display: grid; 52 | grid-template-rows: auto 1fr; 53 | grid-template-columns: 1fr auto; 54 | justify-items: stretch; 55 | align-items: stretch; 56 | overflow-y: auto; 57 | pointer-events: all; 58 | box-shadow: var(--theme-shadow-bottom-large); 59 | transition: background-color var(--layout-transition-extra-fast), box-shadow var(--layout-transition-extra-fast); 60 | } 61 | 62 | @media (min-width: 700px) { 63 | .menu-area { 64 | max-height: 100%; 65 | grid-template-rows: 1fr; 66 | grid-template-columns: 4fr 10fr auto; 67 | overflow: hidden; 68 | position: relative; 69 | } 70 | } 71 | 72 | .menu.is-transparent .menu-area { 73 | pointer-events: none; 74 | } 75 | 76 | .menu-list { 77 | display: none; 78 | } 79 | -------------------------------------------------------------------------------- /src/component/pageLock/index.js: -------------------------------------------------------------------------------- 1 | import { state } from '../state'; 2 | 3 | const pageLock = {}; 4 | 5 | pageLock.render = () => { 6 | 7 | const html = document.querySelector('html'); 8 | 9 | if (state.get.current().modal || state.get.current().menu) { 10 | html.classList.add('is-scroll-disabled'); 11 | } else { 12 | html.classList.remove('is-scroll-disabled'); 13 | } 14 | 15 | }; 16 | 17 | pageLock.init = () => { 18 | state.get.current().modal = false; 19 | state.get.current().menu = false; 20 | }; 21 | 22 | export { pageLock }; 23 | -------------------------------------------------------------------------------- /src/component/reset/index.js: -------------------------------------------------------------------------------- 1 | import './index.css'; 2 | 3 | export const reset = {}; 4 | -------------------------------------------------------------------------------- /src/component/shade/index.css: -------------------------------------------------------------------------------- 1 | .shade { 2 | background-color: rgba(var(--theme-accent), calc(var(--theme-shade-opacity) / 100)); 3 | position: fixed; 4 | top: -1em; 5 | left: -1em; 6 | width: calc(100vw + 2em); 7 | height: calc(100vh + 2em); 8 | opacity: 0; 9 | z-index: var(--z-index-shade); 10 | transition: background-color var(--layout-transition-extra-fast), opacity var(--layout-transition-extra-fast); 11 | pointer-events: all; 12 | backdrop-filter: blur(calc(var(--theme-shade-blur) * 1px)); 13 | } 14 | 15 | .shade.is-transparent { 16 | pointer-events: none; 17 | } 18 | -------------------------------------------------------------------------------- /src/component/shade/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../utility/node'; 2 | 3 | import './index.css'; 4 | 5 | const Shade = function() { 6 | 7 | this.element = { 8 | shade: node('div|class:shade') 9 | }; 10 | 11 | this.open = () => { 12 | const body = document.querySelector('body'); 13 | 14 | this.element.shade.classList.add('is-transparent'); 15 | 16 | this.element.shade.addEventListener('transitionend', (event) => { 17 | if (event.propertyName === 'opacity' && getComputedStyle(this.element.shade).opacity == 0) { 18 | body.removeChild(this.element.shade); 19 | } 20 | }); 21 | 22 | body.appendChild(this.element.shade); 23 | 24 | getComputedStyle(this.element.shade).opacity; 25 | 26 | this.element.shade.classList.remove('is-transparent'); 27 | 28 | this.element.shade.classList.add('is-opaque'); 29 | }; 30 | 31 | this.close = () => { 32 | 33 | this.element.shade.classList.remove('is-opaque'); 34 | 35 | this.element.shade.classList.add('is-transparent'); 36 | 37 | clearTimeout(this.delayedForceRemove); 38 | 39 | this.delayedForceRemove = setTimeout(() => { 40 | 41 | const body = document.querySelector('body'); 42 | 43 | if (body.contains(this.element.shade)) { 44 | body.removeChild(this.element.shade); 45 | } 46 | 47 | }, 6000); 48 | 49 | }; 50 | 51 | this.delayedForceRemove = null; 52 | 53 | this.shade = () => { 54 | return this.element.shade; 55 | }; 56 | 57 | }; 58 | 59 | export { Shade }; 60 | -------------------------------------------------------------------------------- /src/component/splash/index.css: -------------------------------------------------------------------------------- 1 | .splash { 2 | font-size: 1rem; 3 | display: inline-grid; 4 | grid-template-columns: auto auto; 5 | grid-gap: var(--wrap-space); 6 | align-items: center; 7 | justify-items: start; 8 | } 9 | 10 | .splash-logo {} 11 | 12 | .splash-description { 13 | display: flex; 14 | flex-direction: column; 15 | align-items: flex-start; 16 | gap: 0.25em; 17 | } 18 | 19 | .splash-name { 20 | margin-bottom: 0; 21 | } 22 | 23 | .splash-version-number:not(:last-child), 24 | .splash-version-name:not(:last-child) { 25 | margin-bottom: 0; 26 | } 27 | 28 | .splash-version-number { 29 | background-color: rgb(var(--theme-accent)); 30 | color: hsl(var(--theme-accent-text)); 31 | border-radius: calc(var(--theme-radius) * 0.01em); 32 | padding: 0 0.5em; 33 | } 34 | -------------------------------------------------------------------------------- /src/component/splash/index.js: -------------------------------------------------------------------------------- 1 | import { version } from '../version'; 2 | import { node } from '../../utility/node'; 3 | 4 | import { Logo } from '../logo'; 5 | 6 | import { APP_NAME } from '../../constant'; 7 | 8 | import './index.css'; 9 | 10 | export const Splash = function() { 11 | 12 | this.logo = new Logo(); 13 | 14 | this.element = { 15 | splash: node('div|class:splash'), 16 | logo: node('div|class:splash-logo'), 17 | description: { 18 | description: node('div|class:splash-description'), 19 | name: node('h1:' + APP_NAME + '|class:splash-name'), 20 | versionName: node('p:' + version.name + '|class:splash-version-name small'), 21 | versionNumber: node('p:Version ' + version.number + '|class:splash-version-number') 22 | } 23 | }; 24 | 25 | this.assemble = () => { 26 | 27 | this.element.logo.appendChild(this.logo.logo()); 28 | 29 | this.element.splash.appendChild(this.element.logo); 30 | 31 | this.element.description.description.appendChild(this.element.description.name); 32 | 33 | this.element.description.description.appendChild(this.element.description.versionNumber); 34 | 35 | this.element.description.description.appendChild(this.element.description.versionName); 36 | 37 | this.element.splash.appendChild(this.element.description.description); 38 | 39 | }; 40 | 41 | this.splash = () => { 42 | return this.element.splash; 43 | }; 44 | 45 | this.assemble(); 46 | 47 | }; 48 | -------------------------------------------------------------------------------- /src/component/stagedBookmark/index.js: -------------------------------------------------------------------------------- 1 | import { bookmark } from '../bookmark'; 2 | import { bookmarkDefault } from '../bookmarkDefault'; 3 | 4 | export const StagedBookmark = function(bookmarkData) { 5 | 6 | this.link = bookmarkData || JSON.parse(JSON.stringify(bookmarkDefault)); 7 | 8 | this.position = { origin: 0, destination: 0 }; 9 | 10 | this.newBookmark = () => { 11 | this.position.destination = bookmark.all.length + 1; 12 | }; 13 | 14 | this.propagate = { display: false, layout: false, theme: false }; 15 | 16 | }; 17 | -------------------------------------------------------------------------------- /src/component/stagedCustomTheme/index.js: -------------------------------------------------------------------------------- 1 | import { customThemeDefault } from '../customThemeDefault'; 2 | 3 | export const StagedCustomTheme = function(customThemeData) { 4 | 5 | this.theme = customThemeData || JSON.parse(JSON.stringify(customThemeDefault())); 6 | 7 | this.position = 0; 8 | 9 | }; 10 | -------------------------------------------------------------------------------- /src/component/suggest/index.css: -------------------------------------------------------------------------------- 1 | .suggest { 2 | position: relative; 3 | z-index: 1; 4 | font-size: 1em; 5 | } 6 | 7 | .suggest { 8 | background-color: hsl(var(--theme-primary-020)); 9 | margin-top: 0.5em; 10 | padding: 1em; 11 | position: absolute; 12 | top: calc(var(--suggest-top) * 1px); 13 | left: calc(var(--suggest-left) * 1px); 14 | width: calc(var(--suggest-width) * 1px); 15 | max-height: 40vh; 16 | border-radius: calc(var(--theme-radius) * 0.01em); 17 | overflow-y: auto; 18 | z-index: var(--z-index-suggest); 19 | box-shadow: var(--theme-shadow-bottom-large); 20 | opacity: 0; 21 | transition: opacity var(--layout-transition-extra-fast); 22 | } 23 | 24 | .suggest-list { 25 | display: grid; 26 | grid-template-columns: repeat(auto-fill, minmax(6em, 1fr)); 27 | grid-gap: calc((var(--form-space) / 8) * 1em); 28 | } 29 | 30 | .suggest-item { 31 | padding: 0.5em; 32 | width: 100%; 33 | height: 100%; 34 | min-height: 6em; 35 | display: flex; 36 | position: relative; 37 | white-space: inherit; 38 | flex-direction: column; 39 | justify-content: center; 40 | align-items: center; 41 | transition: background-color var(--layout-transition-extra-fast), color var(--layout-transition-extra-fast), border-color var(--layout-transition-extra-fast), box-shadow var(--layout-transition-extra-fast); 42 | } 43 | 44 | .suggest-icon { 45 | font-size: 2em; 46 | } 47 | 48 | .suggest-icon-text { 49 | margin-top: 1em; 50 | font-size: 0.6em; 51 | text-align: center; 52 | line-height: 1.6; 53 | } 54 | -------------------------------------------------------------------------------- /src/component/tab/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --tab-size: 8; 3 | --tab-space: calc((var(--tab-size) / 4) * 1em); 4 | --tab-indicator-top: 0; 5 | --tab-indicator-left: 0; 6 | --tab-indicator-width: 0; 7 | --tab-indicator-height: 0; 8 | } 9 | 10 | .tab { 11 | display: grid; 12 | grid-template-rows: auto auto; 13 | grid-template-areas: 14 | "nav" 15 | "content"; 16 | gap: calc((var(--tab-size) / 4) * 1em); 17 | position: relative; 18 | width: 100%; 19 | } 20 | 21 | .tab-nav { 22 | background-color: hsl(var(--theme-primary-020)); 23 | border-radius: calc((var(--theme-radius) * 0.01em) + ((var(--tab-size) / 4) * 0.125em)); 24 | padding: calc((var(--tab-size) / 4) * 0.125em); 25 | grid-area: nav; 26 | display: flex; 27 | position: relative; 28 | transition: background-color var(--layout-transition-extra-fast); 29 | } 30 | 31 | .tab-nav-group { 32 | flex-grow: 1; 33 | display: flex; 34 | flex-direction: row; 35 | flex-wrap: wrap; 36 | gap: calc((var(--tab-size) / 4) * 0.125em); 37 | } 38 | 39 | @media (min-width: 800px) { 40 | .tab-nav-group { 41 | flex-wrap: nowrap; 42 | } 43 | } 44 | 45 | .tab-nav-button { 46 | background-color: transparent; 47 | flex-grow: 1; 48 | flex-basis: 25%; 49 | z-index: 2; 50 | } 51 | 52 | @media (min-width: 600px) { 53 | .tab-nav-button { 54 | flex-basis: auto; 55 | } 56 | } 57 | 58 | .tab-nav-button.active { 59 | background-color: transparent; 60 | color: hsl(var(--theme-accent-text)); 61 | transition: background-color var(--layout-duration-01), border-color var(--layout-transition-extra-fast), color var(--layout-transition-extra-fast); 62 | } 63 | 64 | .tab-nav-indicator { 65 | background-color: rgb(var(--theme-accent)); 66 | border-radius: calc(var(--theme-radius) * 0.01em); 67 | position: absolute; 68 | top: calc(var(--tab-indicator-top) * 1px); 69 | left: calc(var(--tab-indicator-left) * 1px); 70 | width: calc(var(--tab-indicator-width) * 1px); 71 | height: calc(var(--tab-indicator-height) * 1px); 72 | pointer-events: none; 73 | z-index: 1; 74 | animation: circle-out var(--layout-transition-extra-fast) 1; 75 | } 76 | 77 | .tab-nav-indicator-active .tab-nav-indicator { 78 | animation: none; 79 | transition: top var(--layout-transition-extra-fast), left var(--layout-transition-extra-fast), width var(--layout-transition-extra-fast), height var(--layout-transition-extra-fast); 80 | } 81 | 82 | .tab-content { 83 | grid-area: content; 84 | } 85 | -------------------------------------------------------------------------------- /src/component/themePreset/acrid/index.js: -------------------------------------------------------------------------------- 1 | export const acrid = { 2 | name: 'Acrid', 3 | color: { range: { primary: { h: 301, s: 32 } }, contrast: { start: 11, end: 65 } }, 4 | accent: { hsl: { h: 112, s: 100, l: 42 }, rgb: { r: 29, g: 213, b: 0 } }, 5 | font: { display: { name: 'Titillium Web', weight: 400, style: 'italic' }, ui: { name: 'Inconsolata', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'gradient', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 154, s: 62, l: 24 }, rgb: { r: 23, g: 99, b: 66 } }, 12 | end: { hsl: { h: 300, s: 42, l: 21 }, rgb: { r: 76, g: 31, b: 76 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 20, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/aerial/index.js: -------------------------------------------------------------------------------- 1 | export const aerial = { 2 | name: 'Aerial', 3 | color: { range: { primary: { h: 200, s: 27 } }, contrast: { start: 11, end: 77 } }, 4 | accent: { hsl: { h: 180, s: 100, l: 50 }, rgb: { r: 0, g: 255, b: 255 } }, 5 | font: { display: { name: 'Unica One', weight: 400, style: 'normal' }, ui: { name: 'Inria Sans', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'video', 8 | color: { rgb: { r: 0, g: 0, b: 0 }, hsl: { h: 0, s: 0, l: 0 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 10, opacity: 60, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/videos/1626342605376.mp4?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 20, opacity: 80, vignette: { opacity: 70, start: 90, end: 25 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 2, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 20 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/app/index.js: -------------------------------------------------------------------------------- 1 | import { state } from '../../state'; 2 | import { APP_NAME } from '../../../constant'; 3 | 4 | export const app = { 5 | name: APP_NAME + ' (default)', 6 | color: state.get.default().theme.color, 7 | accent: { hsl: state.get.default().theme.accent.hsl, rgb: state.get.default().theme.accent.rgb }, 8 | font: state.get.default().theme.font, 9 | background: state.get.default().theme.background, 10 | style: state.get.default().theme.style, 11 | shade: state.get.default().theme.shade, 12 | bookmark: state.get.default().theme.bookmark, 13 | toolbar: state.get.default().theme.toolbar 14 | }; 15 | -------------------------------------------------------------------------------- /src/component/themePreset/azure/index.js: -------------------------------------------------------------------------------- 1 | export const azure = { 2 | name: 'Azure', 3 | color: { range: { primary: { h: 215, s: 35 } }, contrast: { start: 13, end: 40 } }, 4 | accent: { hsl: { h: 180, s: 100, l: 50 }, rgb: { r: 0, g: 255, b: 255 } }, 5 | font: { display: { name: 'Unica One', weight: 400, style: 'normal' }, ui: { name: 'Inria Sans', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'gradient', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 180, 11 | start: { hsl: { h: 200, s: 46, l: 33 }, rgb: { r: 45, g: 97, b: 123 } }, 12 | end: { hsl: { h: 212, s: 49, l: 9 }, rgb: { r: 12, g: 22, b: 34 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 10, blur: 10 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 30 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/bean/index.js: -------------------------------------------------------------------------------- 1 | export const bean = { 2 | name: 'Bean', 3 | color: { range: { primary: { h: 191, s: 80 } }, contrast: { start: 7, end: 65 } }, 4 | accent: { hsl: { h: 38, s: 100, l: 50 }, rgb: { r: 255, g: 160, b: 0 } }, 5 | font: { display: { name: 'Life Savers', weight: 400, style: 'normal' }, ui: { name: 'Oswald', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 10, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/black/index.js: -------------------------------------------------------------------------------- 1 | import { state } from '../../state'; 2 | 3 | export const black = { 4 | name: 'Black', 5 | color: { range: { primary: { h: 0, s: 0 } }, contrast: { start: 0, end: 100 } }, 6 | accent: { hsl: { h: 0, s: 0, l: 80 }, rgb: { r: 204, g: 204, b: 204 } }, 7 | font: state.get.default().theme.font, 8 | background: { 9 | type: 'theme', 10 | color: state.get.default().theme.background.color, 11 | gradient: state.get.default().theme.background.gradient, 12 | image: state.get.default().theme.background.image, 13 | video: state.get.default().theme.background.video 14 | }, 15 | style: 'dark', 16 | shade: state.get.default().theme.shade, 17 | bookmark: { 18 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 19 | item: state.get.default().theme.bookmark.item 20 | }, 21 | toolbar: state.get.default().theme.toolbar 22 | }; 23 | -------------------------------------------------------------------------------- /src/component/themePreset/comet/index.js: -------------------------------------------------------------------------------- 1 | export const comet = { 2 | name: 'Comet', 3 | color: { range: { primary: { h: 207, s: 87 } }, contrast: { start: 30, end: 90 } }, 4 | accent: { hsl: { h: 0, s: 0, l: 100 }, rgb: { r: 255, g: 255, b: 255 } }, 5 | font: { display: { name: 'Bungee Hairline', weight: 700, style: 'normal' }, ui: { name: 'Quicksand', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 145, 11 | start: { hsl: { h: 209, s: 100, l: 9 }, rgb: { r: 0, g: 24, b: 46 } }, 12 | end: { hsl: { h: 207, s: 86, l: 27 }, rgb: { r: 10, g: 75, b: 128 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1629912579015.jpeg?raw=true\n\nhttps://github.com/zombieFox/nightTabAssets/blob/main/images/1629911101180.jpeg?raw=true\n\nhttps://github.com/zombieFox/nightTabAssets/blob/main/images/1629911104436.jpeg?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 80, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 15, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 6, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 30 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/corsair/index.js: -------------------------------------------------------------------------------- 1 | export const corsair = { 2 | name: 'Corsair', 3 | color: { range: { primary: { h: 217, s: 46 } }, contrast: { start: 18, end: 74 } }, 4 | accent: { hsl: { h: 59, s: 100, l: 50 }, rgb: { r: 255, g: 251, b: 0 } }, 5 | font: { display: { name: 'Alatsi', weight: 400, style: 'normal' }, ui: { name: 'Source Sans Pro', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 30, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/dash/index.js: -------------------------------------------------------------------------------- 1 | export const dash = { 2 | name: 'Dash', 3 | color: { range: { primary: { h: 211, s: 10 } }, contrast: { start: 50, end: 100 } }, 4 | accent: { hsl: { h: 342, s: 83, l: 40 }, rgb: { r: 187, g: 17, b: 68 } }, 5 | font: { display: { name: 'Fredericka the Great', weight: 400, style: 'normal' }, ui: { name: 'Oswald', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'light', 18 | shade: { opacity: 50, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/deco/index.js: -------------------------------------------------------------------------------- 1 | export const deco = { 2 | name: 'Deco', 3 | color: { range: { primary: { h: 184, s: 38 } }, contrast: { start: 22, end: 75 } }, 4 | accent: { hsl: { h: 0, s: 100, l: 82 }, rgb: { r: 255, g: 161, b: 161 } }, 5 | font: { display: { name: 'Poiret One', weight: 400, style: 'normal' }, ui: { name: 'Lato', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 10, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/earthquake/index.js: -------------------------------------------------------------------------------- 1 | export const earthquake = { 2 | name: 'Earthquake', 3 | color: { range: { primary: { h: 0, s: 13 } }, contrast: { start: 15, end: 40 } }, 4 | accent: { hsl: { h: 48, s: 100, l: 50 }, rgb: { r: 255, g: 204, b: 0 } }, 5 | font: { display: { name: 'Tulpen One', weight: 400, style: 'normal' }, ui: { name: 'Barlow Condensed', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 80, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/funkadelic/index.js: -------------------------------------------------------------------------------- 1 | export const funkadelic = { 2 | name: 'Funkadelic', 3 | color: { range: { primary: { h: 307, s: 100 } }, contrast: { start: 20, end: 70 } }, 4 | accent: { hsl: { h: 60, s: 86, l: 53 }, rgb: { r: 238, g: 238, b: 34 } }, 5 | font: { display: { name: 'Monoton', weight: 400, style: 'normal' }, ui: { name: 'Lato', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 80, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/grimm/index.js: -------------------------------------------------------------------------------- 1 | export const grimm = { 2 | name: 'Grimm', 3 | color: { range: { primary: { h: 283, s: 7 } }, contrast: { start: 18, end: 45 } }, 4 | accent: { hsl: { h: 144, s: 100, l: 50 }, rgb: { r: 0, g: 255, b: 102 } }, 5 | font: { display: { name: 'Griffy', weight: 400, style: 'normal' }, ui: { name: 'Roboto Slab', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 90, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/hive/index.js: -------------------------------------------------------------------------------- 1 | export const hive = { 2 | name: 'Hive', 3 | color: { range: { primary: { h: 37, s: 88 } }, contrast: { start: 33, end: 100 } }, 4 | accent: { hsl: { h: 210, s: 60, l: 23 }, rgb: { r: 23, g: 59, b: 94 } }, 5 | font: { display: { name: 'Kufam', weight: 400, style: 'normal' }, ui: { name: 'Inconsolata', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'video', 8 | color: { rgb: { r: 255, g: 255, b: 255 }, hsl: { h: 0, s: 0, l: 0 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { type: 'url', url: '', blur: 0, grayscale: 0, opacity: 100, scale: 100, accent: 0, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/videos/1627763800511.mp4?raw=true', blur: 0, grayscale: 0, opacity: 16, scale: 100, accent: 0, vignette: { opacity: 50, start: 90, end: 0 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 0, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 10, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 40 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/hypnos/index.js: -------------------------------------------------------------------------------- 1 | export const hypnos = { 2 | name: 'Hypnos', 3 | color: { range: { primary: { h: 243, s: 26 } }, contrast: { start: 15, end: 50 } }, 4 | accent: { hsl: { h: 30, s: 100, l: 80 }, rgb: { r: 255, g: 204, b: 153 } }, 5 | font: { display: { name: 'Shadows Into Light', weight: 100, style: 'normal' }, ui: { name: 'Fira Code', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1628356492462.jpeg?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 5, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 20, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 50 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/infrared/index.js: -------------------------------------------------------------------------------- 1 | export const infrared = { 2 | name: 'Infrared', 3 | color: { range: { primary: { h: 359, s: 100 } }, contrast: { start: 12, end: 85 } }, 4 | accent: { hsl: { h: 0, s: 100, l: 50 }, rgb: { r: 255, g: 0, b: 0 } }, 5 | font: { display: { name: 'Bellota', weight: 400, style: 'normal' }, ui: { name: 'Lexend', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'video', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/videos/1626342620002.mp4?raw=true', blur: 0, grayscale: 100, scale: 100, accent: 50, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 0, blur: 5 }, 19 | bookmark: { 20 | shadow: { opacity: 20, blur: 0, color: { type: 'custom', hsl: { h: 0, s: 0, l: 100 }, rgb: { r: 255, g: 255, b: 255 } } }, 21 | item: { opacity: 60 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/kapow/index.js: -------------------------------------------------------------------------------- 1 | export const kapow = { 2 | name: 'Kapow', 3 | color: { range: { primary: { h: 194, s: 77 } }, contrast: { start: 24, end: 54 } }, 4 | accent: { hsl: { h: 115, s: 100, l: 50 }, rgb: { r: 21, g: 255, b: 0 } }, 5 | font: { display: { name: 'Bangers', weight: 400, style: 'normal' }, ui: { name: 'Sniglet', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626516786268.jpeg?raw=true', blur: 0, grayscale: 100, scale: 100, accent: 0, opacity: 10, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 40, blur: 4 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 90 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/koto/index.js: -------------------------------------------------------------------------------- 1 | export const koto = { 2 | name: 'Koto', 3 | color: { range: { primary: { h: 231, s: 56 } }, contrast: { start: 13, end: 60 } }, 4 | accent: { hsl: { h: 341, s: 100, l: 52 }, rgb: { r: 255, g: 12, b: 88 } }, 5 | font: { display: { name: 'Dosis', weight: 200, style: 'normal' }, ui: { name: 'Montserrat', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626365116841.jpeg?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 20, opacity: 50, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 0, blur: 10 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/lex/index.js: -------------------------------------------------------------------------------- 1 | export const lex = { 2 | name: 'Lex', 3 | color: { range: { primary: { h: 278, s: 73 } }, contrast: { start: 10, end: 60 } }, 4 | accent: { hsl: { h: 160, s: 100, l: 50 }, rgb: { r: 0, g: 255, b: 170 } }, 5 | font: { display: { name: 'Autour One', weight: 400, style: 'normal' }, ui: { name: 'Solway', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'gradient', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 0, 11 | start: { hsl: { h: 222, s: 72, l: 25 }, rgb: { r: 18, g: 45, b: 110 } }, 12 | end: { hsl: { h: 299, s: 72, l: 25 }, rgb: { r: 108, g: 18, b: 110 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 90, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 15 } 22 | }, 23 | toolbar: { opacity: 15 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/macaroon/index.js: -------------------------------------------------------------------------------- 1 | export const macaroon = { 2 | name: 'Macaroon', 3 | color: { range: { primary: { h: 301, s: 28 } }, contrast: { start: 55, end: 80 } }, 4 | accent: { hsl: { h: 241, s: 51, l: 62 }, rgb: { r: 110, g: 109, b: 208 } }, 5 | font: { display: { name: 'Calistoga', weight: 400, style: 'normal' }, ui: { name: 'Source Sans Pro', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'video', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/videos/1626342625654.mp4?raw=true', blur: 0, grayscale: 90, scale: 100, accent: 0, opacity: 10, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'light', 18 | shade: { opacity: 30, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/marker/index.js: -------------------------------------------------------------------------------- 1 | export const marker = { 2 | name: 'Marker', 3 | color: { range: { primary: { h: 0, s: 0 } }, contrast: { start: 56, end: 96 } }, 4 | accent: { hsl: { h: 210, s: 33, l: 20 }, rgb: { r: 34, g: 51, b: 68 } }, 5 | font: { display: { name: 'Permanent Marker', weight: 400, style: 'normal' }, ui: { name: 'Roboto Condensed', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626365108115.jpeg?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 25, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'light', 18 | shade: { opacity: 30, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 10, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 60 } 22 | }, 23 | toolbar: { opacity: 20 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/midnight/index.js: -------------------------------------------------------------------------------- 1 | export const midnight = { 2 | name: 'Midnight', 3 | color: { range: { primary: { h: 221, s: 40 } }, contrast: { start: 12, end: 50 } }, 4 | accent: { hsl: { h: 236, s: 100, l: 50 }, rgb: { r: 0, g: 17, b: 255 } }, 5 | font: { display: { name: 'Megrim', weight: 400, style: 'normal' }, ui: { name: 'Lato', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'video', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/videos/1626351787997.mp4?raw=true', blur: 0, grayscale: 100, scale: 100, accent: 15, opacity: 30, vignette: { opacity: 40, start: 90, end: 50 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 10, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/mint/index.js: -------------------------------------------------------------------------------- 1 | export const mint = { 2 | name: 'Mint', 3 | color: { range: { primary: { h: 157, s: 50 } }, contrast: { start: 12, end: 50 } }, 4 | accent: { hsl: { h: 169, s: 100, l: 68 }, rgb: { r: 94, g: 255, b: 226 } }, 5 | font: { display: { name: 'Unica One', weight: 400, style: 'normal' }, ui: { name: 'Montserrat', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'color', 8 | color: { hsl: { h: 154, s: 69, l: 32 }, rgb: { r: 25, g: 138, b: 89 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 40, blur: 20 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/neon/index.js: -------------------------------------------------------------------------------- 1 | export const neon = { 2 | name: 'Neon', 3 | color: { range: { primary: { h: 219, s: 45, l: 22 } }, contrast: { start: 15, end: 85 } }, 4 | accent: { hsl: { h: 192, s: 100, l: 50 }, rgb: { r: 0, g: 204, b: 255 } }, 5 | font: { display: { name: 'Dosis', weight: 300, style: 'normal' }, ui: { name: 'Inria Sans', weight: 300, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { rgb: { r: 0, g: 0, b: 0 }, hsl: { h: 0, s: 0, l: 0 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1629141035201.jpeg?raw=true', blur: 0, opacity: 50, scale: 100, grayscale: 0, accent: 0, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, opacity: 100, scale: 100, grayscale: 0, accent: 0, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 8, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 45 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/nord/index.js: -------------------------------------------------------------------------------- 1 | export const nord = { 2 | name: 'Nord', 3 | color: { range: { primary: { h: 220, s: 16 } }, contrast: { start: 15, end: 50 } }, 4 | accent: { hsl: { h: 213, s: 32, l: 52 }, rgb: { r: 94, g: 129, b: 172 } }, 5 | font: { display: { name: 'Rubik', weight: 400, style: 'normal' }, ui: { name: 'Inter', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 10, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/obsidian/index.js: -------------------------------------------------------------------------------- 1 | export const obsidian = { 2 | name: 'Obsidian', 3 | color: { range: { primary: { h: 200, s: 10 } }, contrast: { start: 5, end: 50 } }, 4 | accent: { hsl: { h: 180, s: 100, l: 50 }, rgb: { r: 0, g: 255, b: 255 } }, 5 | font: { display: { name: 'Zilla Slab', weight: 700, style: 'normal' }, ui: { name: 'Montserrat', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1629141031788.jpeg?raw=true', blur: 0, opacity: 10, scale: 100, grayscale: 0, accent: 0, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 50, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/origin/index.js: -------------------------------------------------------------------------------- 1 | export const origin = { 2 | name: 'Origin', 3 | color: { range: { primary: { h: 222, s: 14 } }, contrast: { start: 8, end: 88 } }, 4 | accent: { hsl: { h: 30, s: 100, l: 50 }, rgb: { r: 255, g: 128, b: 0 } }, 5 | font: { display: { name: 'Fira Sans', weight: 400, style: 'normal' }, ui: { name: 'Noto Sans', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626472271306.jpeg?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 20, vignette: { opacity: 20, start: 90, end: 40 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 0, blur: 10 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 20 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/outrun/index.js: -------------------------------------------------------------------------------- 1 | export const outrun = { 2 | name: 'Outrun', 3 | color: { range: { primary: { h: 227, s: 52 } }, contrast: { start: 20, end: 80 } }, 4 | accent: { hsl: { h: 316, s: 100, l: 50 }, rgb: { r: 255, g: 0, b: 187 } }, 5 | font: { display: { name: 'Major Mono Display', weight: 400, style: 'normal' }, ui: { name: 'Roboto Condensed', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626365114391.jpeg?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 60, opacity: 70, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 70, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/pepper/index.js: -------------------------------------------------------------------------------- 1 | export const pepper = { 2 | name: 'Pepper', 3 | color: { range: { primary: { h: 0, s: 69 } }, contrast: { start: 15, end: 80 } }, 4 | accent: { rgb: { r: 255, g: 150, b: 0 }, hsl: { h: 35, s: 100, l: 50 } }, 5 | font: { display: { name: 'Big Shoulders Display', weight: 400, style: 'normal' }, ui: { name: 'Montserrat', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 30, 11 | start: { hsl: { h: 358, s: 100, l: 15 }, rgb: { r: 77, g: 0, b: 3 } }, 12 | end: { hsl: { h: 9, s: 99, l: 40 }, rgb: { r: 203, g: 31, b: 1 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1628355202943.jpeg?raw=true', blur: 0, grayscale: 100, scale: 100, accent: 0, opacity: 15, vignette: { opacity: 25, start: 90, end: 35 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 10, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 25 } 22 | }, 23 | toolbar: { opacity: 25 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/point/index.js: -------------------------------------------------------------------------------- 1 | export const point = { 2 | name: 'Point', 3 | color: { range: { primary: { h: 146, s: 20, l: 24 } }, contrast: { start: 20, end: 60 } }, 4 | accent: { hsl: { h: 30, s: 80, l: 63 }, rgb: { r: 236, g: 161, b: 85 } }, 5 | font: { display: { name: 'Klee One', weight: 600, style: 'normal' }, ui: { name: 'Klee One', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1629583136673.jpeg?raw=true\n\nhttps://github.com/zombieFox/nightTabAssets/blob/main/images/1629583172118.jpeg?raw=true\n\nhttps://github.com/zombieFox/nightTabAssets/blob/main/images/1629583176908.jpeg?raw=true\n\nhttps://github.com/zombieFox/nightTabAssets/blob/main/images/1629583180203.jpeg?raw=true\n\nhttps://github.com/zombieFox/nightTabAssets/blob/main/images/1629583182863.jpeg?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 25, vignette: { opacity: 55, start: 90, end: 10 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 4, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 45 } 22 | }, 23 | toolbar: { opacity: 45 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/pumpkin/index.js: -------------------------------------------------------------------------------- 1 | export const pumpkin = { 2 | name: 'Pumpkin', 3 | color: { range: { primary: { h: 198, s: 0 } }, contrast: { start: 10, end: 60 } }, 4 | accent: { hsl: { h: 25, s: 86, l: 53 }, rgb: { r: 238, g: 119, b: 34 } }, 5 | font: { display: { name: 'Girassol', weight: 400, style: 'normal' }, ui: { name: 'Muli', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 10, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/replica/index.js: -------------------------------------------------------------------------------- 1 | export const replica = { 2 | name: 'Replica', 3 | color: { range: { primary: { h: 212, s: 23 } }, contrast: { start: 54, end: 100 } }, 4 | accent: { hsl: { h: 210, s: 40, l: 30 }, rgb: { r: 51, g: 85, b: 119 } }, 5 | font: { display: { name: 'Abel', weight: 400, style: 'normal' }, ui: { name: 'Raleway', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { rgb: { r: 255, g: 255, b: 255 }, hsl: { h: 0, s: 0, l: 0 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626366863277.jpeg?raw=true', blur: 0, grayscale: 0, opacity: 40, scale: 100, accent: 0, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, opacity: 50, scale: 100, accent: 0, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'light', 18 | shade: { opacity: 50, blur: 5 }, 19 | bookmark: { 20 | shadow: { opacity: 40, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 80 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/rumble/index.js: -------------------------------------------------------------------------------- 1 | export const rumble = { 2 | name: 'Rumble', 3 | color: { range: { primary: { h: 267, s: 10 } }, contrast: { start: 16, end: 40 } }, 4 | accent: { hsl: { h: 340, s: 100, l: 38 }, rgb: { r: 196, g: 0, b: 66 } }, 5 | font: { display: { name: 'Odibee Sans', weight: 400, style: 'normal' }, ui: { name: 'Roboto Condensed', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1628615254892.jpeg?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 12, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 20, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 50 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/savage/index.js: -------------------------------------------------------------------------------- 1 | export const savage = { 2 | name: 'Savage', 3 | color: { range: { primary: { h: 35, s: 7 } }, contrast: { start: 5, end: 30 } }, 4 | accent: { hsl: { h: 0, s: 100, l: 50 }, rgb: { r: 255, g: 0, b: 0 } }, 5 | font: { display: { name: 'Metal Mania', weight: 400, style: 'normal' }, ui: { name: 'Lato', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'gradient', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 180, 11 | start: { hsl: { h: 30, s: 5, l: 7 }, rgb: { r: 20, g: 19, b: 18 } }, 12 | end: { hsl: { h: 0, s: 100, l: 13 }, rgb: { r: 66, g: 0, b: 0 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 80, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/scoria/index.js: -------------------------------------------------------------------------------- 1 | export const scoria = { 2 | name: 'Scoria', 3 | color: { range: { primary: { h: 338, s: 76 } }, contrast: { start: 20, end: 65 } }, 4 | accent: { hsl: { h: 210, s: 80, l: 63 }, rgb: { r: 85, g: 161, b: 236 } }, 5 | font: { display: { name: 'Zen Loop', weight: 400, style: 'normal' }, ui: { name: 'Montserrat', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 40, l: 17 }, rgb: { r: 26, g: 37, b: 61 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626775107287.jpeg?raw=true', blur: 4, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 0, blur: 90 }, 19 | bookmark: { 20 | shadow: { opacity: 10, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 80 } 22 | }, 23 | toolbar: { opacity: 80 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/snow/index.js: -------------------------------------------------------------------------------- 1 | export const snow = { 2 | name: 'Snow', 3 | color: { range: { primary: { h: 217, s: 46 } }, contrast: { start: 75, end: 95 } }, 4 | accent: { hsl: { h: 191, s: 59, l: 82 }, rgb: { r: 181, g: 226, b: 236 } }, 5 | font: { display: { name: 'Righteous', weight: 400, style: 'normal' }, ui: { name: 'Raleway', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'gradient', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 360, 11 | start: { hsl: { h: 286, s: 15, l: 96 }, rgb: { r: 246, g: 243, b: 246 } }, 12 | end: { hsl: { h: 204, s: 52, l: 81 }, rgb: { r: 181, g: 212, b: 232 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'light', 18 | shade: { opacity: 60, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 80 } 22 | }, 23 | toolbar: { opacity: 80 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/sol/index.js: -------------------------------------------------------------------------------- 1 | export const sol = { 2 | name: 'Sol', 3 | color: { range: { primary: { h: 52, s: 100 } }, contrast: { start: 0, end: 90 } }, 4 | accent: { hsl: { h: 44, s: 100, l: 50 }, rgb: { r: 255, g: 185, b: 0 } }, 5 | font: { display: { name: 'Fredoka One', weight: 400, style: 'normal' }, ui: { name: 'Muli', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'accent', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'light', 18 | shade: { opacity: 60, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 10 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/steel/index.js: -------------------------------------------------------------------------------- 1 | export const steel = { 2 | name: 'Steel', 3 | color: { range: { primary: { h: 214, s: 30 } }, contrast: { start: 20, end: 80 } }, 4 | accent: { hsl: { h: 203, s: 33, l: 35 }, rgb: { r: 59, g: 95, b: 118 } }, 5 | font: { display: { name: 'Abel', weight: 400, style: 'normal' }, ui: { name: 'Raleway', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'theme', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'light', 18 | shade: { opacity: 70, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 100 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/stria/index.js: -------------------------------------------------------------------------------- 1 | export const stria = { 2 | name: 'Stria', 3 | color: { range: { primary: { h: 305, s: 20 } }, contrast: { start: 20, end: 48 } }, 4 | accent: { hsl: { h: 30, s: 80, l: 63 }, rgb: { r: 236, g: 161, b: 85 } }, 5 | font: { display: { name: 'Gowun Batang', weight: 400, style: 'normal' }, ui: { name: '', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626366147967.jpeg?raw=true', blur: 0, grayscale: 52, scale: 100, accent: 0, opacity: 40, vignette: { opacity: 25, start: 90, end: 20 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 0, blur: 10 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 50 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/terra/index.js: -------------------------------------------------------------------------------- 1 | export const terra = { 2 | name: 'Terra', 3 | color: { range: { primary: { h: 29, s: 28 } }, contrast: { start: 17, end: 83 } }, 4 | accent: { hsl: { h: 270, s: 80, l: 37 }, rgb: { r: 94, g: 19, b: 170 } }, 5 | font: { display: { name: 'Sansita Swashed', weight: 400, style: 'normal' }, ui: { name: '', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'gradient', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 180, 11 | start: { hsl: { h: 46, s: 52, l: 70 }, rgb: { r: 219, g: 200, b: 140 } }, 12 | end: { hsl: { h: 342, s: 16, l: 52 }, rgb: { r: 152, g: 113, b: 125 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'light', 18 | shade: { opacity: 4, blur: 4 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/trine/index.js: -------------------------------------------------------------------------------- 1 | export const trine = { 2 | name: 'Trine', 3 | color: { range: { primary: { h: 228, s: 71 } }, contrast: { start: 10, end: 60 } }, 4 | accent: { hsl: { h: 180, s: 100, l: 50 }, rgb: { r: 0, g: 255, b: 255 } }, 5 | font: { display: { name: 'Josefin Sans', weight: 300, style: 'normal' }, ui: { name: 'Roboto Slab', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626365111390.jpeg?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 30, vignette: { opacity: 50, start: 95, end: 60 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 10, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 100 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/umbra/index.js: -------------------------------------------------------------------------------- 1 | export const umbra = { 2 | name: 'Umbra', 3 | color: { range: { primary: { h: 214, s: 30 } }, contrast: { start: 20, end: 80 } }, 4 | accent: { hsl: { h: 151, s: 63, l: 55 }, rgb: { r: 68, g: 213, b: 143 } }, 5 | font: { display: { name: 'Abel', weight: 400, style: 'normal' }, ui: { name: 'Raleway', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1628946282879.jpeg?raw=true', blur: 0, grayscale: 100, scale: 100, accent: 0, opacity: 20, vignette: { opacity: 31, start: 90, end: 0 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 0, blur: 10 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 70 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/vanadium/index.js: -------------------------------------------------------------------------------- 1 | export const vanadium = { 2 | name: 'Vanadium', 3 | color: { range: { primary: { h: 218, s: 33 } }, contrast: { start: 15, end: 65 } }, 4 | accent: { hsl: { h: 30, s: 100, l: 50 }, rgb: { r: 255, g: 128, b: 0 } }, 5 | font: { display: { name: 'Grenze Gotisch', weight: 100, style: 'normal' }, ui: { name: 'Roboto', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'video', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/videos/1626342631982.mp4?raw=true', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 30, vignette: { opacity: 60, start: 90, end: 20 } } 16 | }, 17 | style: 'dark', 18 | shade: { opacity: 20, blur: 10 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 40 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/viper/index.js: -------------------------------------------------------------------------------- 1 | export const viper = { 2 | name: 'Viper', 3 | color: { range: { primary: { h: 111, s: 34 } }, contrast: { start: 17, end: 90 } }, 4 | accent: { hsl: { h: 173, s: 100, l: 25 }, rgb: { r: 0, g: 128, b: 113 } }, 5 | font: { display: { name: 'Georama', weight: 500, style: 'normal' }, ui: { name: 'Lora', weight: 400, style: 'normal' } }, 6 | background: { 7 | type: 'image', 8 | color: { hsl: { h: 221, s: 47, l: 17 }, rgb: { r: 23, g: 36, b: 64 } }, 9 | gradient: { 10 | angle: 160, 11 | start: { hsl: { h: 206, s: 16, l: 40 }, rgb: { r: 86, g: 104, b: 118 } }, 12 | end: { hsl: { h: 219, s: 28, l: 12 }, rgb: { r: 22, g: 28, b: 39 } } 13 | }, 14 | image: { url: 'https://github.com/zombieFox/nightTabAssets/blob/main/images/1626368964266.jpeg?raw=true', blur: 0, grayscale: 100, scale: 100, accent: 20, opacity: 22, vignette: { opacity: 0, start: 90, end: 70 } }, 15 | video: { url: '', blur: 0, grayscale: 0, scale: 100, accent: 0, opacity: 100, vignette: { opacity: 0, start: 90, end: 70 } } 16 | }, 17 | style: 'light', 18 | shade: { opacity: 0, blur: 0 }, 19 | bookmark: { 20 | shadow: { opacity: 0, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 21 | item: { opacity: 20 } 22 | }, 23 | toolbar: { opacity: 0 } 24 | }; 25 | -------------------------------------------------------------------------------- /src/component/themePreset/white/index.js: -------------------------------------------------------------------------------- 1 | import { state } from '../../state'; 2 | 3 | export const white = { 4 | name: 'White', 5 | color: { range: { primary: { h: 0, s: 0 } }, contrast: { start: 0, end: 100 } }, 6 | accent: { hsl: { h: 0, s: 0, l: 20 }, rgb: { r: 51, g: 51, b: 51 } }, 7 | font: state.get.default().theme.font, 8 | background: { 9 | type: 'theme', 10 | color: state.get.default().theme.background.color, 11 | gradient: state.get.default().theme.background.gradient, 12 | image: state.get.default().theme.background.image, 13 | video: state.get.default().theme.background.video 14 | }, 15 | style: 'light', 16 | shade: state.get.default().theme.shade, 17 | bookmark: { 18 | shadow: { opacity: 100, blur: 0, color: { type: 'theme', hsl: { h: 0, s: 0, l: 0 }, rgb: { r: 0, g: 0, b: 0 } } }, 19 | item: state.get.default().theme.bookmark.item 20 | }, 21 | toolbar: state.get.default().theme.toolbar 22 | }; 23 | -------------------------------------------------------------------------------- /src/component/toolbar/index.js: -------------------------------------------------------------------------------- 1 | import { ToolbarControl } from '../toolbarControl'; 2 | 3 | const toolbar = {}; 4 | 5 | toolbar.current = null; 6 | 7 | toolbar.bar = {}; 8 | 9 | toolbar.bar.render = () => { 10 | 11 | toolbar.current = new ToolbarControl(); 12 | 13 | const body = document.querySelector('body'); 14 | 15 | body.appendChild(toolbar.current.toolbar()); 16 | 17 | }; 18 | 19 | toolbar.init = () => { 20 | toolbar.bar.render(); 21 | toolbar.current.update.edit(); 22 | }; 23 | 24 | export { toolbar }; 25 | -------------------------------------------------------------------------------- /src/component/update/index.js: -------------------------------------------------------------------------------- 1 | import { version } from '../version'; 2 | import { updateLegacy } from '../updateLegacy'; 3 | 4 | const update = {}; 5 | 6 | update.mod = updateLegacy.get(); 7 | 8 | 9 | update.mod['4.0.0'] = function(data) { 10 | 11 | data.state.bookmark.newTab = false; 12 | 13 | data.state.theme.toolbar = { opacity: 100 }; 14 | 15 | delete data.state.toolbar.style; 16 | 17 | data.state.theme.bookmark.item = { opacity: 100 }; 18 | 19 | data.state.theme.bookmark.shadow.blur = data.state.bookmark.shadow.blur; 20 | 21 | delete data.state.bookmark.shadow.blur; 22 | 23 | data.state.theme.color.contrast = { 24 | start: data.state.theme.color.lightness.start, 25 | end: data.state.theme.color.lightness.end 26 | }; 27 | 28 | delete data.state.theme.color.lightness; 29 | 30 | data.state.theme.color.shades = 14; 31 | 32 | data.state.theme.background.image.vignette = { opacity: 0, start: 90, end: 70 }; 33 | 34 | data.state.theme.background.video.vignette = { opacity: 0, start: 90, end: 70 }; 35 | 36 | data.bookmark.forEach(item => { 37 | item.display.gutter = 25; 38 | item.color.opacity = item.color.opacity * 100; 39 | }); 40 | 41 | data.state.theme.custom = { all: [], edit: false }; 42 | 43 | return data; 44 | 45 | }; 46 | 47 | update.run = (data) => { 48 | 49 | // loop over all updates in mod.all object 50 | for (var key in update.mod) { 51 | if (version.compare(data.version, key) == -1) { 52 | console.log('\t > running update', key); 53 | data = update.mod[key](data); 54 | data.version = key; 55 | } 56 | } 57 | 58 | // if no update is needed version bump 59 | if (version.compare(data.version, version.number) == -1) { 60 | console.log('\t > no state data to update, version bump to', version.number); 61 | data.version = version.number; 62 | } 63 | 64 | return data; 65 | 66 | }; 67 | 68 | export { update }; 69 | -------------------------------------------------------------------------------- /src/component/version/index.js: -------------------------------------------------------------------------------- 1 | export const version = {}; 2 | 3 | version.number = '4.2.0'; 4 | 5 | version.name = 'Magnificent Nightingale'; 6 | 7 | version.compare = (a, b) => { 8 | 9 | let pa = a.split('.'); 10 | 11 | let pb = b.split('.'); 12 | 13 | for (let i = 0; i < 3; i++) { 14 | 15 | let na = Number(pa[i]); 16 | 17 | let nb = Number(pb[i]); 18 | 19 | if (na > nb) { 20 | return 1; 21 | } 22 | 23 | if (nb > na) { 24 | return -1; 25 | } 26 | 27 | if (!isNaN(na) && isNaN(nb)) { 28 | return 1; 29 | } 30 | 31 | if (isNaN(na) && !isNaN(nb)) { 32 | return -1; 33 | } 34 | 35 | } 36 | 37 | return 0; 38 | }; 39 | -------------------------------------------------------------------------------- /src/component/video/index.js: -------------------------------------------------------------------------------- 1 | import { node } from '../../utility/node'; 2 | import { isValidString } from '../../utility/isValidString'; 3 | 4 | export const Video = function({ 5 | url = false 6 | } = {}) { 7 | 8 | this.video = node('video|autoplay,loop,muted'); 9 | 10 | this.source = node('source'); 11 | 12 | this.video.appendChild(this.source); 13 | 14 | this.play = () => { 15 | this.video.play(); 16 | }; 17 | 18 | this.pause = () => { 19 | var playPromise = this.video.play(); 20 | 21 | if (playPromise !== undefined) { 22 | playPromise.then(() => { 23 | this.video.pause(); 24 | }); 25 | } 26 | }; 27 | 28 | this.autoPause = () => { 29 | 30 | if (document.visibilityState === 'visible') { 31 | this.video.play(); 32 | } else { 33 | this.video.pause(); 34 | } 35 | 36 | }; 37 | 38 | this.assemble = () => { 39 | 40 | this.video.muted = true; 41 | 42 | this.video.loop = true; 43 | 44 | this.video.autoplay = true; 45 | 46 | if (url.includes('mp4') || url.endsWith('mp4')) { 47 | 48 | this.source.type = 'video/mp4'; 49 | 50 | } else if (url.includes('webm') || url.endsWith('webm')) { 51 | 52 | this.source.type = 'video/webm'; 53 | 54 | } 55 | 56 | if (isValidString(url)) { 57 | 58 | this.source.src = url; 59 | 60 | } 61 | 62 | }; 63 | 64 | this.bind = {}; 65 | 66 | this.bind.add = () => { 67 | 68 | window.addEventListener('visibilitychange', this.autoPause); 69 | 70 | }; 71 | 72 | this.bind.remove = () => { 73 | 74 | window.removeEventListener('visibilitychange', this.autoPause); 75 | 76 | }; 77 | 78 | this.assemble(); 79 | 80 | }; 81 | -------------------------------------------------------------------------------- /src/constant/index.js: -------------------------------------------------------------------------------- 1 | export const APP_NAME = 'hexagonTab'; 2 | -------------------------------------------------------------------------------- /src/font/fa/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fa/fa-brands-400.ttf -------------------------------------------------------------------------------- /src/font/fa/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fa/fa-brands-400.woff -------------------------------------------------------------------------------- /src/font/fa/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fa/fa-brands-400.woff2 -------------------------------------------------------------------------------- /src/font/fa/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fa/fa-regular-400.ttf -------------------------------------------------------------------------------- /src/font/fa/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fa/fa-regular-400.woff -------------------------------------------------------------------------------- /src/font/fa/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fa/fa-regular-400.woff2 -------------------------------------------------------------------------------- /src/font/fa/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fa/fa-solid-900.ttf -------------------------------------------------------------------------------- /src/font/fa/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fa/fa-solid-900.woff -------------------------------------------------------------------------------- /src/font/fa/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fa/fa-solid-900.woff2 -------------------------------------------------------------------------------- /src/font/fjalla-one/fjalla-one-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fjalla-one/fjalla-one-400.ttf -------------------------------------------------------------------------------- /src/font/fjalla-one/fjalla-one-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fjalla-one/fjalla-one-400.woff -------------------------------------------------------------------------------- /src/font/fjalla-one/fjalla-one-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/fjalla-one/fjalla-one-400.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-300.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-300.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-300.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-400.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-400.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-400.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-600.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-600.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-600.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-600.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-600.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-700.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-700.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-700.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-800.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-800.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-800.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-800.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-800.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-300.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-300.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-300.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-400.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-400.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-400.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-600.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-600.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-600.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-600.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-600.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-700.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-700.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-700.woff2 -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-800.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-800.ttf -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-800.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-800.woff -------------------------------------------------------------------------------- /src/font/open-sans/open-sans-italic-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/font/open-sans/open-sans-italic-800.woff2 -------------------------------------------------------------------------------- /src/icon/favicon.svg: -------------------------------------------------------------------------------- 1 | 36 | -------------------------------------------------------------------------------- /src/icon/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/icon/icon-128.png -------------------------------------------------------------------------------- /src/icon/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/icon/icon-16.png -------------------------------------------------------------------------------- /src/icon/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/icon/icon-48.png -------------------------------------------------------------------------------- /src/icon/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zombieFox/hexagonTab/2fb94d9c38cc24ded1c3b469509d416a36a733a4/src/icon/icon-512.png -------------------------------------------------------------------------------- /src/icon/icon-512.svg: -------------------------------------------------------------------------------- 1 | 36 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 |