From 27322a55f8764b6f3ad94e580b5b21272736862a Mon Sep 17 00:00:00 2001 From: Victor Savinov Date: Tue, 9 Nov 2021 22:52:40 +0300 Subject: [PATCH] v1.5 --- background.js | 147 +++ content-scripts.js | 214 ++-- manifest.json | 26 +- ui/options.html | 2 +- ui/satus/satus.css | 1467 +----------------------- ui/satus/satus.js | 2636 +------------------------------------------- ui/script.js | 769 ++++++------- ui/styles.css | 20 +- 8 files changed, 670 insertions(+), 4611 deletions(-) diff --git a/background.js b/background.js index ac024cc..f9ddd93 100644 --- a/background.js +++ b/background.js @@ -1,5 +1,152 @@ /*-------------------------------------------------------------- >>> BACKGROUND +---------------------------------------------------------------- +# Update listener +# Message listener +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# UPDATE LISTENER +--------------------------------------------------------------*/ + +chrome.runtime.onInstalled.addListener(function (details) { + chrome.storage.local.get(function (items) { + if (items.global) { + var global_items = {}, + founded = false; + + for (var key in items.global) { + var item = items.global[key]; + + if (typeof item === 'string') { + try { + item = JSON.parse(item); + + if (item) { + var value = { + alt: item.altKey, + ctrl: item.ctrlKey, + shift: item.shiftKey + }; + + if (item.hasOwnProperty('key') && item.hasOwnProperty('keyCode')) { + value.keys = {}; + + value.keys[item.keyCode] = { + key: item.key + }; + } + + if (item.click) { + value.click = item.click; + } + + if (item.context) { + value.context = item.context; + } + + if (item.wheel) { + value.wheel = item.wheel < 0 ? -1 : 1; + } + + global_items[key] = value; + + founded = true; + } + } catch (error) { + console.log(error); + } + } + } + + if (founded === true) { + if (items.global.cut) { + global_items.cut = true; + } + + if (items.global.copy) { + global_items.copy = true; + } + + if (items.global.paste) { + global_items.paste = true; + } + + if (items.global.select) { + global_items.select = true; + } + + if (items.global.drag_and_drop) { + global_items.drag_and_drop = true; + } + + items.global = global_items; + } + } + + if (items.websites) { + for (var hostname in items.websites) { + var website = items.websites[hostname], + website_items = {}, + founded = false; + + for (var key in website.items) { + var item = website.items[key]; + + if (typeof item === 'string') { + try { + item = JSON.parse(item); + + if (item) { + var value = { + alt: item.altKey, + ctrl: item.ctrlKey, + shift: item.shiftKey + }; + + if (item.hasOwnProperty('key') && item.hasOwnProperty('keyCode')) { + value.keys = {}; + + value.keys[item.keyCode] = { + key: item.key + }; + } + + if (item.click) { + value.click = item.click; + } + + if (item.context) { + value.context = item.context; + } + + if (item.wheel) { + value.wheel = item.wheel < 0 ? -1 : 1; + } + + website_items[key] = value; + + founded = true; + } + } catch (error) { + console.log(error); + } + } + } + + if (founded === true) { + website.items = website_items; + } + } + } + + chrome.storage.local.set(items); + }); +}); + + +/*-------------------------------------------------------------- +# MESSAGE LISTENER --------------------------------------------------------------*/ chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) { diff --git a/content-scripts.js b/content-scripts.js index d506db8..f5b0893 100644 --- a/content-scripts.js +++ b/content-scripts.js @@ -19,11 +19,11 @@ --------------------------------------------------------------*/ var extension = { - hostname: location.hostname, - storage: { - data: {} - } -}; + hostname: location.hostname, + storage: { + data: {} + } + }; /*-------------------------------------------------------------- @@ -88,36 +88,22 @@ chrome.runtime.sendMessage({ }); - - - - - - - - - - - - - - /*--------------------------------------------------------------- 1.0 FUNCTION ---------------------------------------------------------------*/ var SETTINGS = { - enabled: true -}, -HID = { - key: false, - shiftKey: false, - ctrlKey: false, - altKey: false, - click: false, - context: false, - wheel: false -}; + enabled: true + }, + HID = { + alt: false, + ctrl: false, + shift: false, + keys: {}, + wheel: 0, + click: false, + context: false + }; function isset(variable) { if (typeof variable === 'undefined' || variable === null) { @@ -130,19 +116,35 @@ function isset(variable) { function prevent(event) { if (isset(SETTINGS.enabled) === false || SETTINGS.enabled === true) { for (var key in SETTINGS.data) { - var data = JSON.parse(SETTINGS.data[key]); - - if ( - (data.key === HID.key || isset(data.key) === false) && - (data.shiftKey === HID.shiftKey || isset(data.shiftKey) === false) && - (data.ctrlKey === HID.ctrlKey || isset(data.ctrlKey) === false) && - (data.altKey === HID.altKey || isset(data.altKey) === false) && - data.click === HID.click && - data.context === HID.context && - data.wheel === HID.wheel - ) { - console.log('STOP'); - event.stopPropagation(); + var item = SETTINGS.data[key], + same_keys = true; + + if (item && typeof item === 'object') { + if (HID.keys && item.keys) { + for (var code in HID.keys) { + if (!item.keys[code]) { + same_keys = false; + } + } + + for (var code in item.keys) { + if (!HID.keys[code]) { + same_keys = false; + } + } + } + + if ( + same_keys === true && + (item.shift === HID.shift || isset(item.shift) === false) && + (item.ctrl === HID.ctrl || isset(item.ctrl) === false) && + (item.alt === HID.alt || isset(item.alt) === false) && + (item.click === HID.click || isset(item.click) === false) && + (item.context === HID.context || isset(item.context) === false) && + (item.wheel === HID.wheel || isset(item.wheel) === false) + ) { + event.stopPropagation(); + } } } } @@ -150,37 +152,35 @@ function prevent(event) { function hid_keyboard(event) { HID = { - key: event.key, - shiftKey: event.shiftKey, - ctrlKey: event.ctrlKey, - altKey: event.altKey, + alt: false, + ctrl: false, + shift: false, + keys: {}, + wheel: 0, click: false, - context: false, - wheel: false + context: false }; - - if (HID.key === 'Shift') { - HID.shiftKey = true; - } - - if (HID.key === 'Control') { - HID.ctrlKey = true; - } - - if (HID.key === 'Alt') { - HID.altKey = true; + + if (event.code === 'AltLeft' || event.code === 'AltRight') { + HID.alt = true; + } else if (event.code === 'ControlLeft' || event.code === 'ControlRight') { + HID.ctrl = true; + } else if (event.code === 'ShiftLeft' || event.code === 'ShiftRight') { + HID.shift = true; + } else { + HID.keys[event.keyCode] = true; } } function update() { - chrome.storage.local.get(function(items) { - var host = location.ancestorOrigins && location.ancestorOrigins[0] && location.ancestorOrigins[0].split('/')[2] || location.host; + chrome.storage.local.get(function (items) { + var host = extension.hostname || location.hostname; SETTINGS.data = items.global || {}; if (items.websites && items.websites[host]) { SETTINGS.enabled = items.websites[host].enabled; - + if (items.websites[host].items) { SETTINGS.data = Object.assign(SETTINGS.data, items.websites[host].items); } @@ -192,9 +192,9 @@ update(); chrome.storage.onChanged.addListener(update); -chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { +chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { if (window.self === window.top && request === 'requestTabUrl') { - sendResponse(location.host); + sendResponse(location.hostname); } }); @@ -203,17 +203,17 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { 2.0 KEYBOARD ---------------------------------------------------------------*/ -window.addEventListener('keydown', function(event) { +window.addEventListener('keydown', function (event) { hid_keyboard(event); prevent(event); }, true); -window.addEventListener('keypress', function(event) { +window.addEventListener('keypress', function (event) { hid_keyboard(event); prevent(event); }, true); -window.addEventListener('keyup', function(event) { +window.addEventListener('keyup', function (event) { hid_keyboard(event); prevent(event); }, true); @@ -223,43 +223,43 @@ window.addEventListener('keyup', function(event) { 3.0 MOUSE ---------------------------------------------------------------*/ -window.addEventListener('click', function(event) { +window.addEventListener('click', function (event) { HID.click = true; HID.context = false; HID.wheel = false; - + prevent(event); - + HID = { - key: false, - shiftKey: false, - ctrlKey: false, - altKey: false, + alt: false, + ctrl: false, + shift: false, + keys: {}, + wheel: 0, click: false, - context: false, - wheel: false + context: false }; }, true); -window.addEventListener('contextmenu', function(event) { +window.addEventListener('contextmenu', function (event) { HID.click = false; HID.context = true; HID.wheel = false; - + prevent(event); }, true); -window.addEventListener('wheel', function(event) { +window.addEventListener('wheel', function (event) { HID.click = false; HID.context = false; - HID.wheel = true; - + HID.wheel = event.deltaY < 0 ? -1 : 1; + prevent(event); }, true); -window.addEventListener('mousedown', function(event) { +window.addEventListener('mousedown', function (event) { HID.wheel = false; - + if (event.button === 0) { HID.click = true; HID.context = false; @@ -267,13 +267,13 @@ window.addEventListener('mousedown', function(event) { HID.click = false; HID.context = true; } - + prevent(event); }, true); -window.addEventListener('mouseup', function(event) { +window.addEventListener('mouseup', function (event) { HID.wheel = false; - + if (event.button === 0) { HID.click = true; HID.context = false; @@ -281,84 +281,84 @@ window.addEventListener('mouseup', function(event) { HID.click = false; HID.context = true; } - + prevent(event); - + if (event.button === 2) { HID = { - key: false, - shiftKey: false, - ctrlKey: false, - altKey: false, + alt: false, + ctrl: false, + shift: false, + keys: {}, + wheel: 0, click: false, - context: false, - wheel: false + context: false }; } }, true); -window.addEventListener('cut', function(event) { +window.addEventListener('cut', function (event) { if (SETTINGS.data.cut !== false) { event.stopPropagation(); } }, true); -window.addEventListener('copy', function(event) { +window.addEventListener('copy', function (event) { if (SETTINGS.data.copy !== false) { console.log('COPY', event); event.stopPropagation(); } }, true); -window.addEventListener('paste', function(event) { +window.addEventListener('paste', function (event) { if (SETTINGS.data.paste !== false) { event.stopPropagation(); } }, true); -window.addEventListener('select', function(event) { +window.addEventListener('select', function (event) { if (SETTINGS.data.select !== false) { event.stopPropagation(); } }, true); -window.addEventListener('drag', function(event) { +window.addEventListener('drag', function (event) { if (SETTINGS.data.drag_and_drop === true) { event.stopPropagation(); } }, true); -window.addEventListener('dragend', function(event) { +window.addEventListener('dragend', function (event) { if (SETTINGS.data.drag_and_drop === true) { event.stopPropagation(); } }, true); -window.addEventListener('dragenter', function(event) { +window.addEventListener('dragenter', function (event) { if (SETTINGS.data.drag_and_drop === true) { event.stopPropagation(); } }, true); -window.addEventListener('dragstart', function(event) { +window.addEventListener('dragstart', function (event) { if (SETTINGS.data.drag_and_drop === true) { event.stopPropagation(); } }, true); -window.addEventListener('dragleave', function(event) { +window.addEventListener('dragleave', function (event) { if (SETTINGS.data.drag_and_drop === true) { event.stopPropagation(); } }, true); -window.addEventListener('dragover', function(event) { +window.addEventListener('dragover', function (event) { if (SETTINGS.data.drag_and_drop === true) { event.stopPropagation(); } }, true); -window.addEventListener('drop', function(event) { +window.addEventListener('drop', function (event) { if (SETTINGS.data.drag_and_drop === true) { event.stopPropagation(); } @@ -374,4 +374,4 @@ window.addEventListener('mousemove', prevent, true);*/ /*window.addEventListener('touchend', prevent, true); window.addEventListener('touchmove', prevent, true); -window.addEventListener('touchstart', prevent, true);*/ +window.addEventListener('touchstart', prevent, true);*/ \ No newline at end of file diff --git a/manifest.json b/manifest.json index 1ff7b0e..1d2a610 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "HID control prevention", "description": "__MSG_description_ext__", - "version": "1.3", + "version": "1.5", "default_locale": "en", "icons": { "16": "icons/16.png", @@ -19,16 +19,18 @@ "default_popup": "ui/popup.html" }, "options_page": "ui/options.html", - "content_scripts": [{ - "all_frames": true, - "js": [ - "content-scripts.js" - ], - "matches": [ - "" - ], - "run_at": "document_start" - }], + "content_scripts": [ + { + "all_frames": true, + "js": [ + "content-scripts.js" + ], + "matches": [ + "" + ], + "run_at": "document_start" + } + ], "optional_permissions": [ "downloads" ], @@ -36,5 +38,5 @@ "chrome://favicon/", "storage" ], - "content_security_policy": "script-src 'self'; object-src 'self'; img-src * data: chrome://favicon;" + "content_security_policy": "script-src 'self'; object-src 'self'; img-src * data: chrome://favicon;" } \ No newline at end of file diff --git a/ui/options.html b/ui/options.html index ffe78bf..b7c60bb 100644 --- a/ui/options.html +++ b/ui/options.html @@ -11,7 +11,7 @@ width: 100%; height: 100vh; margin: 0; - overflow: hidden; + overflow: hidden } diff --git a/ui/satus/satus.css b/ui/satus/satus.css index 3fd879c..5dcc800 100644 --- a/ui/satus/satus.css +++ b/ui/satus/satus.css @@ -1,1466 +1 @@ - -/*-------------------------------------------------------------- ->>> ELEMENTS: ----------------------------------------------------------------- -# Hidden ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# HIDDEN ---------------------------------------------------------------*/ - -[hidden] { - display: none; -} -/*-------------------------------------------------------------- ->>> THEMES: ----------------------------------------------------------------- -# Default ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# DEFAULT ---------------------------------------------------------------*/ - -body { - --satus-primary: #f6b465; - --satus-switch-background: rgba(0,0,0,.08); - --satus-header-background: #fff; - --satus-header-text: #848471; - --satus-layers-background: #f6f6f4; - --satus-layers-text: #848471; - --satus-section-card-background: #fff; - --satus-modal-background: #f6f6f4; - --satus-modal-text: #848471; - --satus-hover: rgba(0, 0, 0, .04); - --satus-text-field--background: #e8e8e3; - --satus-text-field--border: #d6d6cd; - --satus-text-field--text: #848471; - --satus-switch-track: #b8b8b8; - --satus-switch-track--active: var(--satus-primary); - --satus-switch-thumb: #fff; - --satus-tabs: #fff; - --satus-tooltip: rgba(0,0,0,.4); - --satus-sortable-ghost: rgba(0, 0, 0, .80); - --satus-sortable-background: #f9cf9f; - --satus-sortable-text: #fff; - --satus-divider: #e0e0e0; - --satus-tabs-background: #e8e8e3; - --satus-tabs-foreground: #fff; - --satus-context-menu--border: #ccc; - --satus-checkbox--background: rgb(90, 90, 73, .08); - --satus-checkbox--border: rgb(90, 90, 73, .16); - --satus-checkbox--mark: #fff; - --satus-alert-error-background: #fde6e6; - --satus-alert-error-border: #ecd7d7; - --satus-alert-error-color: #ad5f5f; -} - -body[theme=dark] { - --satus-primary: #90a5e0; - --satus-switch-background: rgba(0,0,0,.08); - --satus-header-background: #232b43; - --satus-header-text: #bcc4dc; - --satus-layers-background: #0e111b; - --satus-layers-text: #bcc4dc; - --satus-section-card-background: #1d2335; - --satus-modal-background: #252e46; - --satus-modal-text: #bcc4dc; - --satus-hover: rgba(255, 255, 255, .08); - --satus-text-field--background: #20273c; - --satus-text-field--border: #2e3957; - --satus-text-field--text: #c4c4d4; - --satus-switch-track: #101219; - --satus-switch-track--active: var(--satus-primary); - --satus-switch-thumb: #d7dcea; - --satus-tooltip: rgba(255,255,255,.4); - --satus-sortable-ghost: rgba(255, 255, 255, .8); - --satus-sortable-background: var(--satus-primary); - --satus-sortable-text: #fff; - --satus-divider: #3e4865; - --satus-tabs-background: #1f2433; - --satus-tabs-foreground: #344165; - --satus-context-menu--border: #2e3957; - --satus-checkbox--background: rgb(233, 234, 237, .08); - --satus-checkbox--border: rgb(233, 234, 237, .16); - --satus-checkbox--mark: #fff; - --satus-alert-error-background: #501616; - --satus-alert-error-border: #6f1f1f; - --satus-alert-error-color: #cf7777; -} - -body[theme=black] { - --satus-primary: #8f8f8f; - --satus-switch-background: rgba(255,255,255,.08); - --satus-header-background: #1f1f1f; - --satus-header-text: #ccc; - --satus-layers-background: #000; - --satus-layers-text: #ccc; - --satus-section-card-background: #1a1a1a; - --satus-modal-background: #212121; - --satus-modal-text: #ccc; - --satus-hover: rgba(255, 255, 255, .08); - --satus-text-field--background: #333333; - --satus-text-field--border: #525252; - --satus-text-field--text: #ccc; - --satus-switch-track: #111; - --satus-switch-track--active: var(--satus-primary); - --satus-switch-thumb: #ddd; - --satus-tooltip: rgba(255,255,255,.4); - --satus-sortable-ghost: rgba(255, 255, 255, .8); - --satus-sortable-background: var(--satus-primary); - --satus-sortable-text: #fff; - --satus-divider: #444; - --satus-tabs-background: #111; - --satus-tabs-foreground: #2e2e2e; - --satus-context-menu--border: #525252; - --satus-checkbox--background: rgb(235, 235, 235, .08); - --satus-checkbox--border: rgb(235, 235, 235, .16); - --satus-checkbox--mark: #fff; - --satus-alert-error-background: #501616; - --satus-alert-error-border: #6f1f1f; - --satus-alert-error-color: #cf7777; -} -/*-------------------------------------------------------------- ->>> COLOR PICKER: ----------------------------------------------------------------- -# Button -# Modal ---------------------------------------------------------------*/ - - -/*-------------------------------------------------------------- -# BUTTON ---------------------------------------------------------------*/ - -.satus-color-picker { - font-size: inherit; - position: relative; - display: flex; - box-sizing: border-box; - margin: 0; - cursor: pointer; - color: inherit; - border: none; - outline: none; - background-color: var(--satus-theme-button); - justify-content: space-between; - -webkit-tap-highlight-color: transparent; - align-items: center; - -webkit-appearance: none; -} - -.satus-color-picker__value { - width: 22px; - height: 22px; - border: 2px solid rgba(0, 0, 0, .16); - border-radius: 50%; - background: #fff; -} - - -/*-------------------------------------------------------------- -# MODAL ---------------------------------------------------------------*/ - -.satus-modal--color-picker { - position: relative; -} - -.satus-modal--color-picker .satus-modal__surface { - padding-top: 0; -} - -.satus-color-picker__palette { - position: relative; - overflow: hidden; - width: 100%; - height: 256px; - background-color: #f00; -} - -.satus-color-picker__palette:before { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - content: ''; - background-image: linear-gradient(0deg, black, transparent), linear-gradient(90deg, white, transparent); -} - -.satus-color-picker__cursor { - position: absolute; - width: 5px; - height: 5px; - transform: translate(-50%, -50%); - pointer-events: none; - border: 1px solid #fff; - border-radius: 50%; - box-shadow: 0 0 0 1px #000; -} - -.satus-modal--color-picker .satus-modal__surface .satus-section--color { - margin: 8px 16px 0; - align-items: center; -} - -.satus-color-picker__color { - width: 32px; - height: 32px; - margin: 0 16px 0 0; - border: 2px solid rgba(0, 0, 0, .16); - border-radius: 50%; - background: #f00; -} - -.satus-slider.satus-color-picker__hue { - padding: 0; - flex: 1; -} - -.satus-color-picker__hue .satus-slider__track { - height: 16px; - border-radius: 4px; - background-image: linear-gradient(90deg, #f00, #ff2a00, #f50, #ff7f00, #fa0, #ffd400, #ff0, #d4ff00, #af0, #80ff00, #5f0, #2bff00, #0f0, #00ff2b, #0f5, #00ff80, #0fa, #00ffd5, #0ff, #00d4ff, #0af, #007fff, #05f, #002bff, #00f, #2a00ff, #50f, #7f00ff, #a0f, #d400ff, #f0f, #ff00d4, #f0a, #ff0080, #f05, #ff002b, #f00); -} - -.satus-color-picker__hue .satus-slider__handle { - width: 16px; - height: 16px; - background: #fff; - box-shadow: 0 0 4px rgb(0, 0, 0, .64); -} - -.satus-color-picker__hue::before, -.satus-color-picker__hue .satus-slider__track-fill, -.satus-color-picker__hue .satus-slider__handle:focus::after { - display: none; -} -/*-------------------------------------------------------------- -# MAIN ---------------------------------------------------------------*/ - -.satus-main { - color: var(--satus-main-text); - background: var(--satus-main-background); - overflow-y: auto; - box-sizing: border-box; -} -/*-------------------------------------------------------------- ->>> TABS ---------------------------------------------------------------*/ - -.satus-tabs { - display: flex; - height: 26px !important; -} - -.satus-tabs__content { - position: relative; - overflow: hidden; - width: 100%; - height: 100%; - border: 2px solid var(--satus-tabs-background); - border-radius: 4px; - background: var(--satus-tabs-background); -} - -.satus-tabs__selection { - position: absolute; - z-index: 0; - top: 0; - left: 0; - height: 100%; - transition: left .25s; - border-radius: 4px; - background: var(--satus-tabs-foreground); -} - -.satus-tabs__button { - font: inherit; - position: relative; - z-index: 1; - overflow: hidden; - height: 100%; - padding: 0 4px; - white-space: nowrap; - text-overflow: ellipsis; - color: inherit; - border: none; - background: transparent; - flex: 1; -} - -.satus-tabs__button:hover { - cursor: pointer; -} -/*-------------------------------------------------------------- ->>> MENUBAR ---------------------------------------------------------------*/ - -.satus-menubar, -.satus-menubar ul { - margin: 0; - padding: 0; - list-style: none; - background: var(--satus-menubar-background); - color: var(--satus-menubar-text); -} - -.satus-menubar li > .satus-button { - height: 32px; - font-size: 14px; -} - -.satus-menubar > li > ul { - display: none; - position: absolute; -} - -.satus-menubar > li > ul:hover, -.satus-menubar > li > *:focus + ul { - display: block; -} -/*-------------------------------------------------------------- ->>> RADIO ---------------------------------------------------------------*/ -/*-------------------------------------------------------------- -# BUTTON ---------------------------------------------------------------*/ - -.satus-button { - font: inherit; - position: relative; - display: flex; - overflow: hidden; - height: 48px; - margin: 0; - padding: 8px; - text-align: left; - color: var(--satus-button-text, inherit); - border: none; - background: var(--satus-button-background, transparent); - appearance: none; - align-items: center; -} - -.satus-button:hover { - cursor: pointer; - background-color: var(--satus-hover); -} - -.satus-button[hidden] { - display: none; -} - -.satus-button>svg { - min-width: 20px; -} - -.satus-button>.satus-span--label { - display: block; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} -/*-------------------------------------------------------------- ->>> LIST: ---------------------------------------------------------------*/ - -.satus-list { - list-style: none; - margin: 0; -} - -.satus-list__item { - display: flex; - align-items: center; - justify-content: space-between; - min-height: 48px; -} - -.satus-list__item>*:last-child { - text-align: right; -} -/*-------------------------------------------------------------- ->>> SECTION: ----------------------------------------------------------------- -# Align -# Card ---------------------------------------------------------------*/ - -.satus-section { - display: flex; - box-sizing: border-box; - flex-wrap: wrap; -} - - -/*-------------------------------------------------------------- -# ALIGN ---------------------------------------------------------------*/ - -.satus-section--align-start { - align-items: center; - justify-content: flex-start; -} - -.satus-section--align-end { - align-items: center; - justify-content: flex-end; -} - -.satus-section--space-between { - align-items: center; - justify-content: space-between; -} - -.satus-section--column { - flex-direction: column; -} - - -/*-------------------------------------------------------------- -# CARD ---------------------------------------------------------------*/ - -.satus-section--card { - flex-direction: column; - box-sizing: border-box; - width: 100%; - max-width: 900px; - margin: 8px auto; - padding: 8px 0; - color: var(--satus-section-card-text); - border: 1px solid rgba(0, 0, 0, .1); - border-radius: 8px; - background: var(--satus-section-card-background); - justify-content: stretch; -} - -.satus-section--card>*:not(.satus-button) { - box-sizing: border-box; - min-height: 48px; - padding: 0 16px; - text-align: left; -} - -.satus-section--card>.satus-switch, -.satus-section--card>.satus-select, -.satus-section--card>.satus-radio { - display: flex; - justify-content: space-between; - align-items: center; -} - -.satus-section--card>.satus-button:hover, -.satus-section--card>.satus-switch:hover, -.satus-section--card>.satus-select:hover, -.satus-section--card>.satus-slider:hover, -.satus-section--card>.satus-radio:hover { - background-color: var(--satus-hover); -} - -.satus-section--card>.satus-button { - width: 100%; - padding: 0 16px; -} - -.satus-section--card>.satus-button>svg { - width: 20px; - margin: 2px 16px 0 0; - color: var(--satus-primary); -} -/*-------------------------------------------------------------- -# SCROLLBAR ---------------------------------------------------------------*/ - -::-webkit-scrollbar { - width: 4px; -} - -::-webkit-scrollbar:hover { - width: 8px; -} - -::-webkit-scrollbar-thumb { - background: rgba(0, 0, 0, .3); -} -/*-------------------------------------------------------------- ->>> MODAL ---------------------------------------------------------------*/ - -.satus-modal { - position: absolute; - z-index: 100; - top: 0; - left: 0; - display: flex; - width: 100%; - height: 100vh; - justify-content: center; - align-items: center; -} - -.satus-modal__scrim { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - animation: modalFadeIn 150ms linear forwards; - opacity: 0; - background: rgba(0, 0, 0, .16); - backdrop-filter: blur(8px); -} - -.satus-modal__surface { - display: flex; - overflow-y: auto; - flex-direction: column; - width: 95%; - min-width: 240px; - max-width: 560px; - max-height: 80%; - margin: 0 16px; - padding: 12px 16px; - transform: scale(.8); - animation: modalZoomIn 150ms linear forwards; - animation-delay: 20ms; - opacity: 0; - color: var(--satus-modal-text); - border-radius: 6px; - background-color: var(--satus-modal-background); - box-shadow: inset 0 -1px 1px 1px rgb(0, 0, 0, .1), 0 2px 6px rgb(0, 0, 0, .15); -} - -.satus-modal__surface .satus-section--actions { - display: flex; - width: 100%; - margin: 8px 0 0; - padding: 0; - justify-content: flex-end; - align-items: center; -} - -.satus-modal__surface .satus-section--actions .satus-button { - font-weight: 500; - height: 32px; - margin-left: 8px; - padding: 0 8px; - letter-spacing: .5px; - color: var(--satus-primary); - border-radius: 4px; -} - -.satus-modal--closing .satus-modal__scrim { - animation: modalFadeOut 70ms linear forwards; -} - -.satus-modal--closing .satus-modal__surface { - animation: modalZoomOut 70ms linear forwards; -} - -.satus-modal--vertical .satus-modal__surface { - position: absolute; - top: 8px; - right: 8px; - left: auto; - min-width: 200px; - max-width: 200px; - margin: 0; - padding: 8px 0; - transform-origin: right top; -} - -.satus-modal--vertical .satus-modal__surface>.satus-button, -.satus-modal--vertical .satus-modal__surface>.satus-switch, -.satus-modal--vertical .satus-modal__surface>.satus-select { - display: flex; - height: 36px; - padding: 0 16px; - align-items: center; -} - -.satus-modal--vertical .satus-modal__surface>.satus-tabs { - padding: 0 12px; -} - -.satus-modal--vertical .satus-modal__surface>.satus-span { - font-size: 13px; - font-weight: 500; - margin: 6px 0; - padding: 0 12px; -} - -.satus-modal--vertical .satus-modal__surface>.satus-button:hover, -.satus-modal--vertical .satus-modal__surface>.satus-switch:hover, -.satus-modal--vertical .satus-modal__surface>.satus-select:hover { - background-color: var(--satus-hover); -} - -.satus-modal--vertical .satus-button svg { - width: 20px; - height: 18px; - margin: 0 14px 0 0; - opacity: .75; - flex: 0 0 20px; -} - -.satus-modal--vertical .satus-button .satus-span { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - - -/*-------------------------------------------------------------- -# ANIMATIONS ---------------------------------------------------------------*/ - -@keyframes modalFadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes modalFadeOut { - from { - opacity: 1; - } - to { - opacity: 0; - } -} - -@keyframes modalZoomIn { - from { - transform: scale(.8); - opacity: 0; - } - to { - transform: scale(1); - opacity: 1; - } -} - -@keyframes modalZoomOut { - from { - transform: scale(1); - opacity: 1; - } - to { - transform: scale(.8); - opacity: 0; - } -} -/*-------------------------------------------------------------- ->>> CHECKBOX ---------------------------------------------------------------*/ - -.satus-checkbox { - position: relative; - font: inherit; - display: flex; - color: inherit; - border: none; - background: transparent; - appearance: none; - align-items: center; - justify-content: flex-start; -} - -.satus-checkbox:hover { - cursor: pointer; - background-color: var(--satus-hover); -} - -.satus-checkbox:focus { - outline: none; -} - -.satus-checkbox__content { - display: block; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} - -.satus-checkbox::before { - display: flex; - min-width: 16px; - width: 16px; - height: 16px; - margin: 0 12px 0 0; - content: ''; - border: 1px solid var(--satus-checkbox--border); - border-radius: 6px; - background: var(--satus-checkbox--background); - align-items: center; - justify-content: center; -} - -.satus-checkbox[data-value=true]::before { - background: var(--satus-primary); -} - -.satus-checkbox[data-value=true]::after { - position: absolute; - top: 20px; - left: 20px; - width: 8px; - height: 4px; - content: ''; - transform: rotate(-45deg); - border: 2px solid var(--satus-checkbox--mark); - border-top: none; - border-right: none; -} -/*-------------------------------------------------------------- ->>> SWITCH ----------------------------------------------------------------- -# Container -# Track -# Thumb ---------------------------------------------------------------*/ - - -/*-------------------------------------------------------------- -# CONTAINER ---------------------------------------------------------------*/ - -.satus-switch { - font: inherit; - display: flex; - transition: background-color 75ms; - color: inherit; - border: none; - outline: none; - background-color: transparent; - justify-content: space-between; - align-items: center; -} - -.satus-switch:hover { - cursor: pointer; -} - -.satus-switch__content { - display: flex; - align-items: center; -} - -.satus-switch__content>svg { - width: 20px; - height: 18px; - margin: 0 14px 0 0; - opacity: .75; -} - - -/*-------------------------------------------------------------- -# TRACK ---------------------------------------------------------------*/ - -.satus-switch>i { - width: 38px; - height: 20px; - transition: background-color 150ms; - border-radius: 20px; - background-color: var(--satus-switch-track); - flex: 0 0 38px; -} - -.satus-section--card .satus-switch>i { - margin-left: 16px; -} - -.satus-switch[data-value='true']>i { - background-color: var(--satus-switch-track--active); -} - - -/*-------------------------------------------------------------- -# THUMB ---------------------------------------------------------------*/ - -.satus-switch>i::before { - display: block; - width: 16px; - height: 16px; - margin: 2px; - content: ''; - transition: transform 150ms cubic-bezier(.4, 0, .2, 1); - border-radius: 50%; - background-color: var(--satus-switch-thumb); - will-change: transform; -} - -.satus-switch[data-value='true']>i::before { - transform: translateX(18px); -} -/*-------------------------------------------------------------- ->>> SLIDER ---------------------------------------------------------------*/ - -.satus-slider { - box-sizing: border-box; - width: 100%; - padding: 8px 16px 0; - outline: none; -} - -.satus-slider__container { - position: relative; - height: 32px; - width: 100%; -} - -.satus-slider__track { - position: absolute; - top: 50%; - left: 0; - height: 2px; - width: 100%; - transform: translateY(-50%); -} - -.satus-slider__track::before { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - background: var(--satus-primary); - opacity: .24; - content: ''; -} - -.satus-slider__handle:focus::after { - content: attr(data-value); - position: absolute; - left: 50%; - top: -2px; - background: var(--satus-primary); - color: #fff; - display: block; - transform: translate(-50%, -100%); - padding: 1px 4px; - border-radius: 4px; -} - -.satus-slider__track-fill { - position: absolute; - left: 0; - top: 0; - height: 100%; - background: var(--satus-primary); -} - -.satus-slider__handle { - position: absolute; - width: 10px; - height: 10px; - background: var(--satus-primary); - border-radius: 50%; - transform: translate(-50%, -50%); - top: 50%; - left: 0; -} - -.satus-slider__handle::before { - content: ''; - background: var(--satus-primary); - position: absolute; - left: 50%; - top: 50%; - width: 1px; - height: 1px; - opacity: 0; - border-radius: 50%; - transform: translate(-50%, -50%) scale(1); - transition: .2s; -} - -.satus-slider:focus .satus-slider__handle::before { - transform: translate(-50%, -50%) scale(26); - opacity: .24; -} -/*-------------------------------------------------------------- ->>> SHORTCUT: ----------------------------------------------------------------- -# ---------------------------------------------------------------*/ - -.satus-shortcut { - justify-content: space-between; -} - -.satus-shortcut__value { - text-transform: uppercase; - font-size: 11px; - opacity: .5; -} - -.satus-shortcut__actions { - display: flex; - justify-content: flex-end; -} - -.satus-shortcut__actions .satus-button { - height: 32px; - background: rgba(0,0,0,.15); - margin: 8px 4px 0; - border-radius: 8px; -} - -.satus-shortcut__actions .satus-button:hover { - background: rgba(0,0,0,.25); -} - -.satus-shortcut__primary { - display: flex; - box-sizing: border-box; - width: 100%; - height: 68px; - padding: 16px; - background: rgba(0,0,0,.16); - align-items: center; -} - -.satus-shortcut__key { - display: flex; - box-sizing: border-box; - min-width: 32px; - height: 32px; - padding: 4px 8px; - border-radius: 4px; - background: #fff; - box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1); - align-items: center; - justify-content: center; -} - -.satus-shortcut__plus { - position: relative; - width: 12px; - height: 12px; - margin: 8px; -} - -.satus-shortcut__plus::before { - position: absolute; - top: 0; - left: 5px; - width: 2px; - height: 12px; - content: ''; - background-color: #aaa; -} - -.satus-shortcut__plus::after { - position: absolute; - top: 5px; - left: 0; - width: 12px; - height: 2px; - content: ''; - background-color: #aaa; -} - -.satus-shortcut__mouse { - position: relative; - display: flex; - width: 28px; - height: 36px; - border-radius: 50%; - border-top-left-radius: 12px; - border-top-right-radius: 12px; - background: #fff; - box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1); -} - -.satus-shortcut__mouse>div { - position: absolute; - top: 0; - left: 13px; - width: 2px; - height: 11px; - border-radius: 2px; - background: #ccc; -} - -.satus-shortcut__mouse::before { - position: absolute; - top: -4px; - left: 21px; - width: 2px; - height: 18px; - content: ''; - background: #f96754; -} - -.satus-shortcut__mouse.false::after { - position: absolute; - top: -12px; - left: 17px; - width: 0; - height: 0; - content: ''; - border-right: 5px solid transparent; - border-bottom: 8px solid #f96754; - border-left: 5px solid transparent; -} - -.satus-shortcut__mouse.true::after { - position: absolute; - top: 14px; - left: 17px; - width: 0; - height: 0; - content: ''; - border-top: 8px solid #f96754; - border-right: 5px solid transparent; - border-left: 5px solid transparent; -} - -.satus-section_shortcut { - width: 100%; - margin: 8px 0 0; - justify-content: flex-end; -} - -.satus-button_shortcut { - font-weight: 500; - overflow: hidden; - height: 28px; - min-height: 28px; - margin-right: 2px; - padding: 4px 8px; - text-transform: uppercase; - color: #f96754; - border-radius: 4px; -} -/*-------------------------------------------------------------- ->>> BASE ---------------------------------------------------------------*/ - -.satus-base{ - display: flex; - flex-direction: column; - width: 100%; - height: 100%; -} -/*-------------------------------------------------------------- ->>> TEXT FIELD ---------------------------------------------------------------*/ - -.satus-text-field { - position: relative; - padding: 0 16px; - background-color: var(--satus-text-field--background); - border-radius: 8px; - color: var(--satus-text-field--text); - overflow: hidden; - display: flex; -} - -.satus-text-field__pre { - display: flex; - position: relative; - height: 100%; - margin: 0; - padding: 0; - overflow: hidden; - align-items: center; - flex: 1; -} - -.satus-text-field__input { - font: inherit; - position: absolute; - top: 0; - left: 0; - width: 100%; - min-width: 0; - max-width: none; - height: 100%; - min-height: 0; - max-height: none; - margin: 0; - padding: 0; - opacity: 0; - border: none; - appearance: none; - z-index: 9; -} - -.satus-text-field__hidden-text { - position: absolute; - pointer-events: none; - opacity: 0; -} - -.satus-text-field__text { - position: absolute; - top: 0; - left: 0; - display: flex; - height: 100%; - margin: 0; - align-items: center; -} - -.satus-text-field__cursor { - position: absolute; - top: 6px; - left: 0; - display: none; - width: 2px; - height: 25px; - animation: blink 1s step-end 8; - background: #fa0; -} - -.satus-text-field__selection { - position: absolute; - top: 5px; - left: 0; - display: none; - width: 0; - height: 25px; - border: 1px solid rgba(255, 255, 255, .2); - border-radius: 3px; - background: rgba(255, 255, 255, .1); -} - -.satus-text-field__input:focus + * + * + * + .satus-text-field__cursor, -.satus-text-field__selection:not([disabled]) { - display: block; -} - -@keyframes blink { - from, - to { - opacity: 1; - } - 50% { - opacity: 0; - } -} - - -/*-------------------------------------------------------------- -# SYNTAX HIGHLIGHTING ---------------------------------------------------------------*/ - -.satus-text-field__text>.group { - color: #47ff47; - background-color: rgb(71, 255, 71, .16); -} - -.satus-text-field__text>.character-class { - color: #ffc247; - background-color: rgb(255, 170, 0, .16); -} - -.satus-text-field__text>.quantifier { - color: #47c2ff; - background-color: rgb(71, 194, 255, .16); -} - -.satus-text-field__text>.anchor { - color: #47c2ff; - background-color: rgb(71, 194, 255, .16); -} - -.satus-text-field__text>.metasequence { - color: #47ff47; - background-color: rgb(71, 255, 71, .16); -} - -.satus-text-field__text>.text { - color: #c4c4d4; - background-color: rgb(196, 196, 212, .16); -} -/*-------------------------------------------------------------- ->>> HEADER ---------------------------------------------------------------*/ - -.satus-header { - z-index: 1; - display: flex; - box-sizing: border-box; - height: 56px; - padding: 0 12px; - color: var(--satus-header-text); - background: var(--satus-header-background); - box-shadow: 0 1px 2px rgb(47, 41, 34, .16); - align-items: center; - justify-content: space-between; -} - -.satus-header .satus-button { - width: 40px; - min-width: 40px; - height: 40px; - padding: 8px; - color: inherit; - border-radius: 50%; -} - -.satus-header .satus-section--align-start>* { - margin-right: 8px; -} - -.satus-header .satus-span--title { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - flex: 1; -} -/*-------------------------------------------------------------- ->>> ALERT ---------------------------------------------------------------*/ - -.satus-alert { - display: flex; - box-sizing: border-box; - min-height: 48px; - margin: 8px 0 0; - padding: 8px 16px; - border-radius: 8px; - align-items: center; -} - -.satus-alert--error { - color: var(--satus-alert-error-color); - border: 1px solid var(--satus-alert-error-border); - background: var(--satus-alert-error-background); -} -/*-------------------------------------------------------------- ->>> LAYERS ---------------------------------------------------------------*/ - -.satus-layers { - position: relative; - overflow: hidden; - color: var(--satus-layers-text); - background: var(--satus-layers-background); - flex: 1; -} - -.satus-layer { - position: absolute; - top: 0; - left: 0; - display: flex; - overflow-y: auto; - box-sizing: border-box; - width: 100%; - height: 100%; - padding: 0 12px; - flex-wrap: wrap; - align-content: flex-start; -} -/*-------------------------------------------------------------- ->>> DIVIDER ---------------------------------------------------------------*/ - -.satus-divider { - height: 1px; - margin: 16px 0 12px; - background: var(--satus-divider); -} -/*-------------------------------------------------------------- -# INPUT ---------------------------------------------------------------*/ - -.satus-input[type=text], -.satus-input[type=password] { - font: inherit; - box-sizing: border-box; - width: 100%; - margin: 0; - padding: 0; - padding: 0 8px; - color: var(--satus-text-field--text, inherit); - border: none; - outline: none; - background: none; - appearance: none; - font-size: 16px; - margin: 8px 0; - padding: 4px 8px; - border: 1px solid var(--satus-text-field--border); - border-radius: 4px; - background-color: var(--satus-text-field--background); -} -/**/ - -.satus-aside { - color: var(--satus-aside-text); - background: var(--satus-aside-background); - box-sizing: border-box; -} -/*-------------------------------------------------------------- ->>> SELECT ---------------------------------------------------------------*/ - -.satus-select { - position: relative; - display: flex; - box-sizing: border-box; - align-items: center; - justify-content: space-between; -} - -.satus-select__content { - display: flex; - align-items: center; -} - -.satus-select__content > svg { - width: 20px; - - height: 18px; - margin: 0 14px 0 0; - opacity: .75; -} - -.satus-select__value { - margin-left: 16px; - text-align: right; - opacity: .75; -} - -.satus-select select { - font: inherit; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - margin: 0; - padding: 0; - padding: inherit; - cursor: pointer; - opacity: 0; - color: inherit; - border: none; - outline: none; - background: none; - appearance: none; -} - -.satus-select:hover { - cursor: pointer; - background-color: var(--satus-hover); -} -/*-------------------------------------------------------------- ->>> CONTEXT MENU ---------------------------------------------------------------*/ - -.satus-modal--contextmenu .satus-modal__scrim { - background: none; - backdrop-filter: none; - animation: none; - visibility: visible; - opacity: 1; - transform: none; -} - -.satus-modal--contextmenu .satus-modal__surface { - position: absolute; - margin: 0; - box-sizing: border-box; - min-width: 200px; - max-width: 200px; - padding: 4px 0; - border-radius: 4px; - border: 1px solid var(--satus-context-menu--border); - box-shadow: none; - animation: none; - visibility: visible; - opacity: 1; - transform: none; -} - -.satus-modal--contextmenu .satus-modal__surface > * { - -} - -.satus-modal--contextmenu .satus-modal__surface>* { - display: flex; - height: 32px; - padding: 0 16px; - align-items: center; -} - -.satus-modal--contextmenu .satus-modal__surface .satus-button svg { - width: 20px; - height: 18px; - margin: 0 14px 0 0; - opacity: .75; - fill: none; - stroke: var(--satus-primary); - flex: 0 0 20px; -} - -.satus-modal--contextmenu .satus-modal__surface .satus-button .satus-span { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} -/*-------------------------------------------------------------- ->>> PLUVIAM ---------------------------------------------------------------*/ - -.satus-pluviam { - position: absolute; - transform: scale(0); - animation-name: pluviam; - animation-duration: 1000ms; - opacity: var(--satus-pluviam-opacity, .08); - border-radius: 50%; - background: var(--satus-pluviam-background, #000); - animation-fill-mode: forwards; -} - -@keyframes pluviam { - 0% { - transform: scale(0); - opacity: var(--satus-pluviam-opacity, .08); - } - 70% { - transform: scale(.8); - opacity: var(--satus-pluviam-opacity, .08); - } - 100% { - transform: scale(1); - opacity: 0; - } -} -/*-------------------------------------------------------------- ->>> SORTABLE ---------------------------------------------------------------*/ - -.satus-sortable__chosen { - color: var(--satus-sortable-text) !important; - background-color: var(--satus-sortable-background) !important; -} - -.satus-sortable__ghost { - position: fixed !important; - z-index: 999 !important; - top: 0 !important; - left: 0 !important; - pointer-events: none !important; - box-shadow: 0 1px 3px rgb(0, 0, 0, .2), 0 4px 8px rgb(0, 0, 0, .1), inset 0 0 0 1px rgb(0, 0, 0, .16); - will-change: transform !important; - opacity: .8 !important; -} \ No newline at end of file +[hidden]{display:none}body{--satus-primary:#f6b465;--satus-switch-background:rgba(0,0,0,.08);--satus-header-background:#fff;--satus-header-text:#848471;--satus-layers-background:#f6f6f4;--satus-layers-text:#848471;--satus-section-card-background:#fff;--satus-modal-background:#f6f6f4;--satus-modal-text:#848471;--satus-hover:rgba(0, 0, 0, .04);--satus-text-field--background:#e8e8e3;--satus-text-field--border:#d6d6cd;--satus-text-field--text:#848471;--satus-switch-track:#e0e0e0;--satus-switch-track--active:var(--satus-primary);--satus-switch-thumb:#fff;--satus-tabs:#fff;--satus-tooltip:rgba(0,0,0,.4);--satus-sortable-ghost:rgba(0, 0, 0, .80);--satus-sortable-background:#f9cf9f;--satus-sortable-text:#fff;--satus-divider:#e0e0e0;--satus-tabs-background:#e8e8e3;--satus-tabs-foreground:#fff;--satus-context-menu--border:#ccc;--satus-checkbox--background:rgb(90, 90, 73, .08);--satus-checkbox--border:rgb(90, 90, 73, .16);--satus-checkbox--mark:#fff;--satus-alert-error-background:#fde6e6;--satus-alert-error-border:#ecd7d7;--satus-alert-error-color:#ad5f5f}body[theme=dark]{--satus-primary:#90a5e0;--satus-switch-background:rgba(0,0,0,.08);--satus-header-background:#232b43;--satus-header-text:#bcc4dc;--satus-layers-background:#0e111b;--satus-layers-text:#bcc4dc;--satus-section-card-background:#1d2335;--satus-modal-background:#252e46;--satus-modal-text:#bcc4dc;--satus-hover:rgba(255, 255, 255, .08);--satus-text-field--background:#20273c;--satus-text-field--border:#2e3957;--satus-text-field--text:#c4c4d4;--satus-switch-track:#101219;--satus-switch-track--active:var(--satus-primary);--satus-switch-thumb:#d7dcea;--satus-tooltip:rgba(255,255,255,.4);--satus-sortable-ghost:rgba(255, 255, 255, .8);--satus-sortable-background:var(--satus-primary);--satus-sortable-text:#fff;--satus-divider:#3e4865;--satus-tabs-background:#1f2433;--satus-tabs-foreground:#344165;--satus-context-menu--border:#2e3957;--satus-checkbox--background:rgb(233, 234, 237, .08);--satus-checkbox--border:rgb(233, 234, 237, .16);--satus-checkbox--mark:#fff;--satus-alert-error-background:#501616;--satus-alert-error-border:#6f1f1f;--satus-alert-error-color:#cf7777}body[theme=black]{--satus-primary:#8f8f8f;--satus-switch-background:rgba(255,255,255,.08);--satus-header-background:#1f1f1f;--satus-header-text:#ccc;--satus-layers-background:#000;--satus-layers-text:#ccc;--satus-section-card-background:#1a1a1a;--satus-modal-background:#212121;--satus-modal-text:#ccc;--satus-hover:rgba(255, 255, 255, .08);--satus-text-field--background:#333333;--satus-text-field--border:#525252;--satus-text-field--text:#ccc;--satus-switch-track:#111;--satus-switch-track--active:var(--satus-primary);--satus-switch-thumb:#ddd;--satus-tooltip:rgba(255,255,255,.4);--satus-sortable-ghost:rgba(255, 255, 255, .8);--satus-sortable-background:var(--satus-primary);--satus-sortable-text:#fff;--satus-divider:#444;--satus-tabs-background:#111;--satus-tabs-foreground:#2e2e2e;--satus-context-menu--border:#525252;--satus-checkbox--background:rgb(235, 235, 235, .08);--satus-checkbox--border:rgb(235, 235, 235, .16);--satus-checkbox--mark:#fff;--satus-alert-error-background:#501616;--satus-alert-error-border:#6f1f1f;--satus-alert-error-color:#cf7777}.satus-color-picker{font-size:inherit;position:relative;display:flex;box-sizing:border-box;margin:0;cursor:pointer;color:inherit;border:none;outline:0;background-color:var(--satus-theme-button);justify-content:space-between;-webkit-tap-highlight-color:transparent;align-items:center;-webkit-appearance:none}.satus-color-picker__value{width:22px;height:22px;border:2px solid rgba(0,0,0,.16);border-radius:50%;background:#fff}.satus-modal--color-picker{position:relative}.satus-modal--color-picker .satus-modal__surface{padding-top:0}.satus-color-picker__palette{position:relative;overflow:hidden;width:100%;height:256px;background-color:red}.satus-color-picker__palette:before{position:absolute;top:0;left:0;width:100%;height:100%;content:'';background-image:linear-gradient(0deg,#000,transparent),linear-gradient(90deg,#fff,transparent)}.satus-color-picker__cursor{position:absolute;width:5px;height:5px;transform:translate(-50%,-50%);pointer-events:none;border:1px solid #fff;border-radius:50%;box-shadow:0 0 0 1px #000}.satus-modal--color-picker .satus-modal__surface .satus-section--color{margin:8px 16px 0;align-items:center}.satus-color-picker__color{width:32px;height:32px;margin:0 16px 0 0;border:2px solid rgba(0,0,0,.16);border-radius:50%;background:red}.satus-slider.satus-color-picker__hue{padding:0;flex:1}.satus-color-picker__hue .satus-slider__track{height:16px;border-radius:4px;background-image:linear-gradient(90deg,red,#ff2a00,#f50,#ff7f00,#fa0,#ffd400,#ff0,#d4ff00,#af0,#80ff00,#5f0,#2bff00,#0f0,#00ff2b,#0f5,#00ff80,#0fa,#00ffd5,#0ff,#00d4ff,#0af,#007fff,#05f,#002bff,#00f,#2a00ff,#50f,#7f00ff,#a0f,#d400ff,#f0f,#ff00d4,#f0a,#ff0080,#f05,#ff002b,red)}.satus-color-picker__hue .satus-slider__handle{width:16px;height:16px;background:#fff;box-shadow:0 0 4px rgb(0,0,0,.64)}.satus-color-picker__hue .satus-slider__handle:focus::after,.satus-color-picker__hue .satus-slider__track-fill,.satus-color-picker__hue::before{display:none}.satus-main{color:var(--satus-main-text);background:var(--satus-main-background);overflow-y:auto;box-sizing:border-box}.satus-tabs{display:flex;height:26px!important}.satus-tabs__content{position:relative;overflow:hidden;width:100%;height:100%;border:2px solid var(--satus-tabs-background);border-radius:4px;background:var(--satus-tabs-background)}.satus-tabs__selection{position:absolute;z-index:0;top:0;left:0;height:100%;transition:left .25s;border-radius:4px;background:var(--satus-tabs-foreground)}.satus-tabs__button{font:inherit;position:relative;z-index:1;overflow:hidden;height:100%;padding:0 4px;white-space:nowrap;text-overflow:ellipsis;color:inherit;border:none;background:0 0;flex:1}.satus-tabs__button:hover{cursor:pointer}.satus-menubar,.satus-menubar ul{margin:0;padding:0;list-style:none;background:var(--satus-menubar-background);color:var(--satus-menubar-text)}.satus-menubar li>.satus-button{height:32px;font-size:14px}.satus-menubar>li>ul{display:none;position:absolute}.satus-menubar>li>:focus+ul,.satus-menubar>li>ul:hover{display:block}.satus-button{font:inherit;position:relative;display:flex;overflow:hidden;height:48px;margin:0;padding:8px;text-align:left;color:var(--satus-button-text,inherit);border:none;background:var(--satus-button-background,transparent);appearance:none;align-items:center}.satus-button:hover{cursor:pointer;background-color:var(--satus-hover)}.satus-button[hidden]{display:none}.satus-button>svg{min-width:20px}.satus-button>.satus-span--label{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.satus-list{list-style:none;margin:0}.satus-list__item{display:flex;align-items:center;justify-content:space-between;min-height:48px}.satus-list__item>:last-child{text-align:right}.satus-section{display:flex;box-sizing:border-box;flex-wrap:wrap}.satus-section--align-start{align-items:center;justify-content:flex-start}.satus-section--align-end{align-items:center;justify-content:flex-end}.satus-section--space-between{align-items:center;justify-content:space-between}.satus-section--column{flex-direction:column}.satus-section--card{flex-direction:column;box-sizing:border-box;width:100%;max-width:900px;margin:8px auto;padding:8px 0;color:var(--satus-section-card-text);border:1px solid rgba(0,0,0,.1);border-radius:8px;background:var(--satus-section-card-background);justify-content:stretch}.satus-section--card>:not(.satus-button){box-sizing:border-box;min-height:48px;padding:0 16px;text-align:left}.satus-section--card>.satus-radio,.satus-section--card>.satus-select,.satus-section--card>.satus-switch{display:flex;justify-content:space-between;align-items:center}.satus-section--card>.satus-button:hover,.satus-section--card>.satus-radio:hover,.satus-section--card>.satus-select:hover,.satus-section--card>.satus-slider:hover,.satus-section--card>.satus-switch:hover{background-color:var(--satus-hover)}.satus-section--card>.satus-button{width:100%;padding:0 16px}.satus-section--card>.satus-button>svg{width:20px;margin:2px 16px 0 0;color:var(--satus-primary)}.satus-section--card>.satus-span{display:flex;align-items:center}::-webkit-scrollbar{width:4px}::-webkit-scrollbar:hover{width:8px}::-webkit-scrollbar-thumb{background:rgba(0,0,0,.3)}.satus-modal{position:absolute;z-index:100;top:0;left:0;display:flex;width:100%;height:100vh;justify-content:center;align-items:center}.satus-modal__scrim{position:absolute;top:0;left:0;width:100%;height:100%;animation:modalFadeIn 150ms linear forwards;opacity:0;background:rgba(0,0,0,.16);backdrop-filter:blur(8px)}.satus-modal__surface{display:flex;overflow-y:auto;flex-direction:column;width:95%;min-width:240px;max-width:560px;max-height:80%;margin:0 16px;padding:12px 16px;transform:scale(.8);animation:modalZoomIn 150ms linear forwards;animation-delay:20ms;opacity:0;color:var(--satus-modal-text);border-radius:6px;background-color:var(--satus-modal-background);box-shadow:inset 0 -1px 1px 1px rgb(0,0,0,.1),0 2px 6px rgb(0,0,0,.15)}.satus-modal__surface .satus-section--actions{display:flex;width:100%;margin:8px 0 0;padding:0;justify-content:flex-end;align-items:center}.satus-modal__surface .satus-section--actions .satus-button{font-weight:500;height:32px;margin-left:8px;padding:0 8px;letter-spacing:.5px;color:var(--satus-primary);border-radius:4px}.satus-modal--closing .satus-modal__scrim{animation:modalFadeOut 70ms linear forwards}.satus-modal--closing .satus-modal__surface{animation:modalZoomOut 70ms linear forwards}.satus-modal--vertical .satus-modal__surface{position:absolute;top:8px;right:8px;left:auto;min-width:200px;max-width:200px;margin:0;padding:8px 0;transform-origin:right top}.satus-modal--vertical .satus-modal__surface>.satus-button,.satus-modal--vertical .satus-modal__surface>.satus-select,.satus-modal--vertical .satus-modal__surface>.satus-switch{display:flex;height:36px;padding:0 16px;align-items:center}.satus-modal--vertical .satus-modal__surface>.satus-tabs{padding:0 12px}.satus-modal--vertical .satus-modal__surface>.satus-span{font-size:13px;font-weight:500;margin:6px 0;padding:0 12px}.satus-modal--vertical .satus-modal__surface>.satus-button:hover,.satus-modal--vertical .satus-modal__surface>.satus-select:hover,.satus-modal--vertical .satus-modal__surface>.satus-switch:hover{background-color:var(--satus-hover)}.satus-modal--vertical .satus-button svg{width:20px;height:18px;margin:0 14px 0 0;opacity:.75;flex:0 0 20px}.satus-modal--vertical .satus-button .satus-span{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@keyframes modalFadeIn{from{opacity:0}to{opacity:1}}@keyframes modalFadeOut{from{opacity:1}to{opacity:0}}@keyframes modalZoomIn{from{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}@keyframes modalZoomOut{from{transform:scale(1);opacity:1}to{transform:scale(.8);opacity:0}}.satus-checkbox{position:relative;font:inherit;display:flex;color:inherit;border:none;background:0 0;appearance:none;align-items:center;justify-content:flex-start}.satus-checkbox:hover{cursor:pointer;background-color:var(--satus-hover)}.satus-checkbox:focus{outline:0}.satus-checkbox__content{display:block;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.satus-checkbox::before{display:flex;min-width:16px;width:16px;height:16px;margin:0 12px 0 0;content:'';border:1px solid var(--satus-checkbox--border);border-radius:6px;background:var(--satus-checkbox--background);align-items:center;justify-content:center}.satus-checkbox[data-value=true]::before{background:var(--satus-primary)}.satus-checkbox[data-value=true]::after{position:absolute;top:20px;left:20px;width:8px;height:4px;content:'';transform:rotate(-45deg);border:2px solid var(--satus-checkbox--mark);border-top:none;border-right:none}.satus-switch{font:inherit;display:flex;transition:background-color 75ms;color:inherit;border:none;outline:0;background-color:transparent;justify-content:space-between;align-items:center}.satus-switch:hover{cursor:pointer}.satus-switch__content{display:flex;align-items:center}.satus-switch__content>svg{width:20px;height:18px;margin:0 14px 0 0;opacity:.75}.satus-switch>i{width:32px;height:18px;transition:background-color 150ms;border-radius:18px;background-color:var(--satus-switch-track);flex:0 0 32px}.satus-section--card .satus-switch>i{margin-left:16px}.satus-switch[data-value=true]>i{background-color:var(--satus-switch-track--active)}.satus-switch>i::before{display:block;width:14px;height:14px;margin:2px;content:'';transition:transform 150ms cubic-bezier(.4,0,.2,1);border-radius:50%;background-color:var(--satus-switch-thumb);will-change:transform}.satus-switch[data-value=true]>i::before{transform:translateX(14px)}.satus-slider{box-sizing:border-box;width:100%;padding:8px 16px 0;outline:0}.satus-slider__container{position:relative;height:32px;width:100%}.satus-slider__track{position:absolute;top:50%;left:0;height:2px;width:100%;transform:translateY(-50%)}.satus-slider__track::before{position:absolute;left:0;top:0;width:100%;height:100%;background:var(--satus-primary);opacity:.24;content:''}.satus-slider__handle:focus::after{content:attr(data-value);position:absolute;left:50%;top:-2px;background:var(--satus-primary);color:#fff;display:block;transform:translate(-50%,-100%);padding:1px 4px;border-radius:4px}.satus-slider__track-fill{position:absolute;left:0;top:0;height:100%;background:var(--satus-primary)}.satus-slider__handle{position:absolute;width:10px;height:10px;background:var(--satus-primary);border-radius:50%;transform:translate(-50%,-50%);top:50%;left:0}.satus-slider__handle::before{content:'';background:var(--satus-primary);position:absolute;left:50%;top:50%;width:1px;height:1px;opacity:0;border-radius:50%;transform:translate(-50%,-50%) scale(1);transition:.2s}.satus-slider:focus .satus-slider__handle::before{transform:translate(-50%,-50%) scale(26);opacity:.24}.satus-shortcut{justify-content:space-between}.satus-shortcut__value{font-size:11px;display:flex;text-transform:uppercase;opacity:.5}.satus-shortcut__actions{display:flex;justify-content:flex-end}.satus-shortcut__actions .satus-button{height:32px;margin:8px 4px 0;border-radius:8px;background:rgba(0,0,0,.15)}.satus-shortcut__actions .satus-button:hover{background:rgba(0,0,0,.25)}.satus-shortcut__primary{display:flex;box-sizing:border-box;width:100%;height:68px;padding:16px;background:rgba(0,0,0,.16);align-items:center}.satus-shortcut__key{display:flex;box-sizing:border-box;min-width:32px;height:32px;padding:4px 8px;border-radius:4px;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.15),inset 0 -3px 0 rgba(0,0,0,.1);align-items:center;justify-content:center}.satus-shortcut__plus{position:relative;width:12px;height:12px;margin:8px}.satus-shortcut__plus::before{position:absolute;top:0;left:5px;width:2px;height:12px;content:'';background-color:#aaa}.satus-shortcut__plus::after{position:absolute;top:5px;left:0;width:12px;height:2px;content:'';background-color:#aaa}.satus-shortcut__mouse{position:relative;display:flex;width:28px;height:36px;border-radius:50%;border-top-left-radius:12px;border-top-right-radius:12px;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.15),inset 0 -3px 0 rgba(0,0,0,.1)}.satus-shortcut__mouse>div{position:absolute;top:0;left:13px;width:2px;height:11px;border-radius:2px;background:#ccc}.satus-shortcut__mouse::before{position:absolute;top:-4px;left:21px;width:2px;height:18px;content:'';background:#f96754}.satus-shortcut__mouse.false::after{position:absolute;top:-12px;left:17px;width:0;height:0;content:'';border-right:5px solid transparent;border-bottom:8px solid #f96754;border-left:5px solid transparent}.satus-shortcut__mouse.true::after{position:absolute;top:14px;left:17px;width:0;height:0;content:'';border-top:8px solid #f96754;border-right:5px solid transparent;border-left:5px solid transparent}.satus-shortcut__mouse.click::before{position:absolute;top:0;left:-1px;width:10px;height:10px;content:'';border-radius:50%;background:#f96754}.satus-shortcut__mouse.context::before{position:absolute;top:0;left:15px;width:10px;height:10px;content:'';border-radius:50%;background:#f96754}.satus-section_shortcut{width:100%;margin:8px 0 0;justify-content:flex-end}.satus-button_shortcut{font-weight:500;overflow:hidden;height:28px;min-height:28px;margin-right:2px;padding:4px 8px;text-transform:uppercase;color:#f96754;border-radius:4px}.satus-base{display:flex;flex-direction:column;width:100%;height:100%}.satus-text-field{position:relative;padding:0 16px;background-color:var(--satus-text-field--background);border-radius:8px;color:var(--satus-text-field--text);overflow:hidden;display:flex}.satus-text-field__pre{display:flex;position:relative;height:100%;margin:0;padding:0;overflow:hidden;align-items:center;flex:1}.satus-text-field__input{font:inherit;position:absolute;top:0;left:0;width:100%;min-width:0;max-width:none;height:100%;min-height:0;max-height:none;margin:0;padding:0;opacity:0;border:none;appearance:none;z-index:9}.satus-text-field__hidden-text{position:absolute;pointer-events:none;opacity:0}.satus-text-field__text{position:absolute;top:0;left:0;display:flex;height:100%;margin:0;align-items:center}.satus-text-field__cursor{position:absolute;top:6px;left:0;display:none;width:2px;height:25px;animation:blink 1s step-end 8;background:#fa0}.satus-text-field__selection{position:absolute;top:5px;left:0;display:none;width:0;height:25px;border:1px solid rgba(255,255,255,.2);border-radius:3px;background:rgba(255,255,255,.1)}.satus-text-field__input:focus+*+*+*+.satus-text-field__cursor,.satus-text-field__selection:not([disabled]){display:block}@keyframes blink{from,to{opacity:1}50%{opacity:0}}.satus-text-field__text>.group{color:#47ff47;background-color:rgb(71,255,71,.16)}.satus-text-field__text>.character-class{color:#ffc247;background-color:rgb(255,170,0,.16)}.satus-text-field__text>.quantifier{color:#47c2ff;background-color:rgb(71,194,255,.16)}.satus-text-field__text>.anchor{color:#47c2ff;background-color:rgb(71,194,255,.16)}.satus-text-field__text>.metasequence{color:#47ff47;background-color:rgb(71,255,71,.16)}.satus-text-field__text>.text{color:#c4c4d4;background-color:rgb(196,196,212,.16)}.satus-header{z-index:1;display:flex;box-sizing:border-box;height:56px;padding:0 12px;color:var(--satus-header-text);background:var(--satus-header-background);box-shadow:0 0 3px rgb(0,0,0,.1);align-items:center;justify-content:space-between}.satus-header .satus-button{width:40px;min-width:40px;height:40px;padding:8px;color:inherit;border-radius:50%}.satus-header .satus-section--align-start>*{margin-right:8px}.satus-header .satus-span--title{font-size:15px;overflow:hidden;white-space:nowrap;letter-spacing:.0125em;text-overflow:ellipsis;flex:1}.satus-alert{display:flex;box-sizing:border-box;min-height:48px;margin:8px 0 0;padding:8px 16px;border-radius:8px;align-items:center}.satus-alert--error{color:var(--satus-alert-error-color);border:1px solid var(--satus-alert-error-border);background:var(--satus-alert-error-background)}.satus-layers{position:relative;overflow:hidden;color:var(--satus-layers-text);background:var(--satus-layers-background);flex:1}.satus-layer{position:absolute;top:0;left:0;display:flex;overflow-y:auto;box-sizing:border-box;width:100%;height:100%;padding:0 12px;flex-wrap:wrap;align-content:flex-start}.satus-divider{height:1px;margin:16px 0 12px;background:var(--satus-divider)}.satus-input[type=password],.satus-input[type=text]{font:inherit;box-sizing:border-box;width:100%;margin:0;padding:0 8px;color:var(--satus-text-field--text,inherit);border:none;outline:0;background:0 0;appearance:none;font-size:16px;margin:8px 0;border:1px solid var(--satus-text-field--border);border-radius:4px;background-color:var(--satus-text-field--background)}.satus-aside{color:var(--satus-aside-text);background:var(--satus-aside-background);box-sizing:border-box}.satus-select{position:relative;display:flex;box-sizing:border-box;align-items:center;justify-content:space-between}.satus-select__content{display:flex;align-items:center}.satus-select__content>svg{width:20px;height:18px;margin:0 14px 0 0;opacity:.75}.satus-select__value{margin-left:16px;text-align:right;opacity:.75}.satus-select select{font:inherit;position:absolute;top:0;left:0;width:100%;height:100%;margin:0;padding:0;padding:inherit;cursor:pointer;opacity:0;color:inherit;border:none;outline:0;background:0 0;appearance:none}.satus-select:hover{cursor:pointer;background-color:var(--satus-hover)}.satus-modal--contextmenu .satus-modal__scrim{background:0 0;backdrop-filter:none;animation:none;visibility:visible;opacity:1;transform:none}.satus-modal--contextmenu .satus-modal__surface{position:absolute;margin:0;box-sizing:border-box;min-width:200px;max-width:200px;padding:4px 0;border-radius:4px;border:1px solid var(--satus-context-menu--border);box-shadow:none;animation:none;visibility:visible;opacity:1;transform:none}.satus-modal--contextmenu .satus-modal__surface>*{display:flex;height:32px;padding:0 16px;align-items:center}.satus-modal--contextmenu .satus-modal__surface .satus-button svg{width:20px;height:18px;margin:0 14px 0 0;opacity:.75;fill:none;stroke:var(--satus-primary);flex:0 0 20px}.satus-modal--contextmenu .satus-modal__surface .satus-button .satus-span{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.satus-pluviam{position:absolute;transform:scale(0);animation-name:pluviam;animation-duration:1s;opacity:var(--satus-pluviam-opacity,.08);border-radius:50%;background:var(--satus-pluviam-background,#000);animation-fill-mode:forwards}@keyframes pluviam{0%{transform:scale(0);opacity:var(--satus-pluviam-opacity,.08)}70%{transform:scale(.8);opacity:var(--satus-pluviam-opacity,.08)}100%{transform:scale(1);opacity:0}}.satus-sortable__chosen{color:var(--satus-sortable-text)!important;background-color:var(--satus-sortable-background)!important}.satus-sortable__ghost{position:fixed!important;z-index:999!important;top:0!important;left:0!important;pointer-events:none!important;box-shadow:0 1px 3px rgb(0,0,0,.2),0 4px 8px rgb(0,0,0,.1),inset 0 0 0 1px rgb(0,0,0,.16);will-change:transform!important;opacity:.8!important} \ No newline at end of file diff --git a/ui/satus/satus.js b/ui/satus/satus.js index e5a97c8..afe66b2 100644 --- a/ui/satus/satus.js +++ b/ui/satus/satus.js @@ -1,2635 +1 @@ - -/*-------------------------------------------------------------- ->>> CORE: ----------------------------------------------------------------- -# Global variable -# Functions -# Render ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# GLOBAL VARIABLE ---------------------------------------------------------------*/ - -var satus = { - components: {}, - events: {}, - locale: { - strings: {} - }, - storage: { - attributes: {}, - data: {} - } -}; - - -/*-------------------------------------------------------------- -# FUNCTIONS ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# APPEND ---------------------------------------------------------------*/ - -satus.append = function (element, container) { - (container || document.body).appendChild(element); -}; - - -/*-------------------------------------------------------------- -# ANIMATION DURATION ---------------------------------------------------------------*/ - -satus.getAnimationDuration = function (element) { - return Number(window.getComputedStyle(element).getPropertyValue('animation-duration').replace(/[^0-9.]/g, '')) * 1000; -}; - - -/*-------------------------------------------------------------- -# APPEND ---------------------------------------------------------------*/ - -satus.attr = function (element, attributes) { - if (attributes) { - for (var key in attributes) { - if (element.is_svg) { - element.setAttributeNS(null, key, attributes[key]); - } else { - var value = attributes[key]; - - if (['placeholder', 'title'].indexOf(key) !== -1) { - value = satus.locale.get(value); - } - - element.setAttribute(key, value); - } - } - } -}; - -satus.elementIndex = function (element) { - return Array.prototype.slice.call(element.parentNode.children).indexOf(element); -}; - - -/*-------------------------------------------------------------- -# DATA ---------------------------------------------------------------*/ - -satus.data = function (element, data) { - if (data) { - for (var key in data) { - element.dataset[key] = data[key]; - } - } -}; - - -/*-------------------------------------------------------------- -# PROPERTIES ---------------------------------------------------------------*/ - -satus.properties = function (element, properties) { - if (properties) { - for (var key in properties) { - element[key] = properties[key]; - } - } -}; - - -/*-------------------------------------------------------------- -# CAMELIZE ---------------------------------------------------------------*/ - -satus.camelize = function (string) { - var result = ''; - - for (var i = 0, l = string.length; i < l; i++) { - var character = string[i]; - - if (character === '-') { - i++; - - result += string[i].toUpperCase(); - } else { - result += character; - } - } - - return result; -}; - - -/*-------------------------------------------------------------- -# SNAKELIZE ---------------------------------------------------------------*/ - -satus.snakelize = function (string) { - return string.replace(/([A-Z])/g, '-$1').toLowerCase(); -}; - - -/*-------------------------------------------------------------- -# CLASS ---------------------------------------------------------------*/ - -satus.class = function (element, string) { - if (string) { - element.className += ' ' + string; - } -}; - - -/*-------------------------------------------------------------- -# EMPTY ---------------------------------------------------------------*/ - -satus.empty = function (element, exclude = []) { - for (var i = element.childNodes.length - 1; i > -1; i--) { - var child = element.childNodes[i]; - - if (exclude.indexOf(child) === -1) { - child.remove(); - } - } -}; - - -/*-------------------------------------------------------------- -# EVENTS ---------------------------------------------------------------*/ - -Object.defineProperty(satus.events, 'add', { - value: function (type, listener) { - if (this.hasOwnProperty(type) === false) { - this[type] = []; - } - - this[type].push(listener); - } -}); - - -/*-------------------------------------------------------------- -# ISSET ---------------------------------------------------------------*/ - -satus.isset = function (variable) { - if (variable === null || variable === undefined) { - return false; - } - - return true; -}; - - -/*-------------------------------------------------------------- -# FETCH ---------------------------------------------------------------*/ - -satus.fetch = function (url, success, error) { - fetch(url).then(function (response) { - if (response.ok) { - response.json().then(success); - } else { - error(); - } - }); -}; - - -/*-------------------------------------------------------------- -# AJAX ---------------------------------------------------------------*/ - -satus.ajax = function (url, success, error) { - var xhr = new XMLHttpRequest(); - - xhr.onload = function () { - success(this.response); - }; - xhr.onerror = function () { - error(success); - }; - - xhr.open('GET', url, true); - xhr.send(); -}; - - -/*-------------------------------------------------------------- -# STORAGE ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# GET ---------------------------------------------------------------*/ - -satus.storage.get = function (name) { - var target = satus.storage.data; - - if (typeof name !== 'string') { - return; - } - - name = name.split('/').filter(function (value) { - return value != ''; - }); - - for (var i = 0, l = name.length; i < l; i++) { - if (satus.isset(target[name[i]])) { - target = target[name[i]]; - } else { - return undefined; - } - } - - return target; -}; - - -/*-------------------------------------------------------------- -# SET ---------------------------------------------------------------*/ - -satus.storage.set = function (name, value) { - var items = {}, - target = satus.storage.data; - - if (typeof name !== 'string') { - return; - } - - name = name.split('/').filter(function (value) { - return value != ''; - }); - - for (var i = 0, l = name.length; i < l; i++) { - var item = name[i]; - - if (i < l - 1) { - - if (target[item]) { - target = target[item]; - } else { - target[item] = {}; - - target = target[item]; - } - } else { - target[item] = value; - } - } - - for (var key in this.data) { - if (typeof this.data[key] !== 'function') { - items[key] = this.data[key]; - } - } - - if (satus.storage.attributes[name]) { - document.body.setAttribute(name, value); - } - - chrome.storage.local.set(items); -}; - - -/*-------------------------------------------------------------- -# IMPORT ---------------------------------------------------------------*/ - -satus.storage.import = function (callback) { - chrome.storage.local.get(function (items) { - for (var key in items) { - if (satus.storage.attributes[key]) { - document.body.setAttribute(key, items[key]); - } - - satus.storage.data[key] = items[key]; - } - - if (callback) { - callback(items); - } - }); -}; - - -/*-------------------------------------------------------------- -# CLEAR ---------------------------------------------------------------*/ - -satus.storage.clear = function (callback) { - this.data = {}; - - chrome.storage.local.clear(callback); -}; - - -/*-------------------------------------------------------------- -# LOCALIZATION ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# GET ---------------------------------------------------------------*/ - -satus.locale.get = function (string) { - return this.strings[string] || string; -}; - - -/*-------------------------------------------------------------- -# IMPORT ---------------------------------------------------------------*/ - -satus.locale.import = function (string, path, callback) { - var language = string || window.navigator.language; - - if (language.indexOf('en') === 0) { - language = 'en'; - } - - if (!path) { - path = '_locales/'; - } - - satus.ajax(path + language + '/messages.json', function (response) { - try { - response = JSON.parse(response); - - for (var key in response) { - satus.locale.strings[key] = response[key].message; - } - } catch (error) { - console.error(error); - } - - callback(); - }, function (success) { - satus.ajax(path + 'en/messages.json', success); - }); -}; - - -/*-------------------------------------------------------------- -# ON ---------------------------------------------------------------*/ - -satus.on = function (element, events) { - if (this.isset(events) && typeof events === 'object') { - for (var selector in events) { - var type = typeof events[selector]; - - if (selector === 'selectionchange') { - element = document; - } - - if (type === 'function') { - element.addEventListener(selector, events[selector]); - } else if (type === 'object') { - element.addEventListener(selector, function (event) { - this.skeleton.on[event.type].parent = this.skeleton; - - if (this.skeleton.on[event.type].component !== 'modal' && this.base && this.base.layers) { - this.base.layers.open(this.skeleton.on[event.type]); - } else { - satus.render(this.skeleton.on[event.type], this.base); - } - }); - } else if (type === 'string') { - element.addEventListener(selector, function () { - var match = this.skeleton.on[event.type].match(/(["'`].+["'`]|[^.()]+)/g), - target = this.base; - - for (var i = 0, l = match.length; i < l; i++) { - var key = match[i]; - - if (target.skeleton[key]) { - target = target.skeleton[key]; - } else { - if (typeof target[key] === 'function') { - target[key](); - } else { - target = target[key]; - } - } - - if (target.rendered) { - target = target.rendered; - } - } - }); - } - } - } -}; - - -/*-------------------------------------------------------------- -# STYLE ---------------------------------------------------------------*/ - -satus.style = function (component, object) { - for (var key in object) { - component.style[key] = object[key]; - } -}; - - -/*-------------------------------------------------------------- -# SEARCH ---------------------------------------------------------------*/ - -satus.search = function (query, object, callback) { - var elements = ['switch', 'select', 'slider', 'shortcut', 'radio', 'color-picker'], - threads = 0, - results = {}; - - query = query.toLowerCase(); - - function parse(items, parent) { - threads++; - - for (var key in items) { - if (key !== 'rendered' && key !== 'base' && key !== 'parent') { - var item = items[key]; - - if (elements.indexOf(item.component) !== -1 && key.indexOf(query) !== -1) { - results[key] = Object.assign({}, item); - } - - if (typeof item === 'object') { - parse(item, items); - } - } - } - - threads--; - - if (threads === 0) { - callback(results); - } - } - - parse(object); -}; - - -/*-------------------------------------------------------------- -# PARENTS ---------------------------------------------------------------*/ - -satus.parents = function (object, components_only) { - function parse(items, parent) { - for (var key in items) { - if (key !== 'rendered' && key !== 'base' && key !== 'parent') { - var item = items[key]; - - if (components_only !== true || item.component) { - item.parent = items; - } - - if (typeof item === 'object' && item.component !== 'shortcut') { - parse(item, items); - } - } - } - } - - parse(object); -}; - - -/*-------------------------------------------------------------- -# TEXT ---------------------------------------------------------------*/ - -satus.text = function (component, value) { - if (typeof value === 'function') { - value = value(); - } - - if (value) { - component.appendChild(document.createTextNode(this.locale.get(value))); - } -}; - - -/*-------------------------------------------------------------- -# DECRYPTION ---------------------------------------------------------------*/ - -satus.decrypt = async function (text, password) { - var iv = text.slice(0, 24).match(/.{2}/g).map(byte => parseInt(byte, 16)), - algorithm = { - name: 'AES-GCM', - iv: new Uint8Array(iv) - }; - - try { - var data = new TextDecoder().decode(await crypto.subtle.decrypt( - algorithm, - await crypto.subtle.importKey( - 'raw', - await crypto.subtle.digest('SHA-256', new TextEncoder().encode(password)), - algorithm, - false, ['decrypt'] - ), - new Uint8Array(atob(text.slice(24)).match(/[\s\S]/g).map(ch => ch.charCodeAt(0))) - )); - } catch (err) { - return false; - } - - return data; -}; - - -/*-------------------------------------------------------------- -# ENCRYPTION ---------------------------------------------------------------*/ - -satus.encrypt = async function (text, password) { - var iv = crypto.getRandomValues(new Uint8Array(12)), - algorithm = { - name: 'AES-GCM', - iv: iv - }; - - return Array.from(iv).map(b => ('00' + b.toString(16)).slice(-2)).join('') + btoa(Array.from(new Uint8Array(await crypto.subtle.encrypt( - algorithm, - await crypto.subtle.importKey('raw', await crypto.subtle.digest('SHA-256', new TextEncoder().encode(password)), algorithm, false, ['encrypt']), - new TextEncoder().encode(text) - ))).map(byte => String.fromCharCode(byte)).join('')); -}; - - -/*-------------------------------------------------------------- -# IS ---------------------------------------------------------------*/ - -satus.isArray = function (array) { - if (Array.isArray(array)) { - return true; - } else { - return false; - } -}; - -satus.isNumber = function (number) { - if (typeof number === 'number' && isNaN(number) === false) { - return true; - } else { - return false; - } -}; - - -/*-------------------------------------------------------------- -# INDEX OF ---------------------------------------------------------------*/ - -satus.indexOf = function (child, parent) { - var index = 0; - - if (satus.isArray(parent)) { - index = parent.indexOf(child); - } else { - while ((child = child.previousElementSibling)) { - index++; - } - } - - return index; -}; - - -/*-------------------------------------------------------------- -# TO INDEX ---------------------------------------------------------------*/ - -satus.toIndex = function (index, child, parent) { - if (satus.isArray(parent)) { - parent.splice(index, 0, parent.splice(satus.indexOf(child, parent), 1)[0]) - } -}; - - -/*-------------------------------------------------------------- -# CLONE ---------------------------------------------------------------*/ - -satus.clone = function (item) { - var clone = item.cloneNode(true), - parent_css = window.getComputedStyle(item.parentNode), - css = window.getComputedStyle(item), - style = ''; - - for (var i = 0, l = css.length; i < l; i++) { - var property = css[i], - value = css.getPropertyValue(property); - - if (property === 'background-color') { - value = parent_css.getPropertyValue('background-color'); - } - - if (['box-shadow', 'left', 'top', 'bottom', 'right', 'opacity'].indexOf(property) === -1) { - style += property + ':' + value + ';'; - } - } - - - clone.setAttribute('style', style); - - return clone; -}; - - -/*-------------------------------------------------------------- -# REMOVE ---------------------------------------------------------------*/ - -satus.remove = function (child, parent) { - if (satus.isArray(parent)) { - parent.splice(satus.indexOf(child, parent), 1); - } -}; - - -/*-------------------------------------------------------------- -# RENDER ---------------------------------------------------------------*/ - -satus.render = function (skeleton, container, skip, property) { - var component; - - if (skeleton.hasOwnProperty('component') && skip !== true) { - var name = skeleton.component, - camelized_name = this.camelize(name); - - if (skeleton.on && skeleton.on.beforerender) { - skeleton.on.beforerender(skeleton); - } - - if (this.components[camelized_name]) { - component = this.components[camelized_name](skeleton); - - if (this.isset(component.inner) === false) { - component.inner = component; - } - } else if (name === 'svg' || container && container.is_svg) { - component = document.createElementNS('http://www.w3.org/2000/svg', name); - - component.is_svg = true; - - component.inner = component; - } else { - component = document.createElement(skeleton.component); - - component.inner = component; - } - - if (component.inner.hasOwnProperty('base') === false && container) { - component.inner.base = container.base; - } - - if (component.inner.base && name === 'layers') { - component.inner.base.layers = component; - } - - skeleton.rendered = component; - component.skeleton = skeleton; - - component.className = (component.className + ' satus-' + skeleton.component).trim(); - - if (skeleton.variant) { - component.className += ' satus-' + skeleton.component + '--' + skeleton.variant; - } - - this.append(component, container); - - container = component.inner || component; - - this.class(component, skeleton.class); - this.style(component, skeleton.style); - this.attr(component, skeleton.attr); - this.data(component, skeleton.data); - this.properties(component, skeleton.properties); - this.on(component, skeleton.on); - this.text(container, skeleton.text); - - if (component.hasOwnProperty('storage') === false && skeleton.storage !== false) { - component.storage = skeleton.storage || property || false; - } - - if (component.hasOwnProperty('storageValue') === false) { - if (component.storage !== false) { - component.storageValue = satus.storage.get(component.storage); - } - - if (skeleton.hasOwnProperty('value') && component.storageValue === undefined) { - component.storageValue = skeleton.value; - } - } - - component.storageChange = function () { - if (this.storage) { - var key = this.storage; - - if (typeof key === 'function') { - key = key(); - } - - satus.storage.set(key, this.storageValue); - } - - this.dispatchEvent(new CustomEvent('change')); - }; - - component.dispatchEvent(new CustomEvent('render')); - - if (skeleton.autofocus === true) { - component.focus(); - } - - if (this.events.hasOwnProperty('render')) { - for (var i = 0, l = this.events['render'].length; i < l; i++) { - this.events['render'][i](component, skeleton); - } - } - } - - if (!component || component.render_children !== false) { - for (var key in skeleton) { - if (key !== 'parent' && skeleton[key] && skeleton[key].hasOwnProperty('component')) { - skeleton[key].parent = skeleton; - - this.render(skeleton[key], container, false, key); - } - } - } - - return component; -}; -/*-------------------------------------------------------------- ->>> COLOR PICKER ---------------------------------------------------------------*/ - -satus.components.colorPicker = function (skeleton) { - var component = document.createElement('button'), - component_label = document.createElement('span'), - component_value = document.createElement('span'); - - component.inner = component_label; - component.valueElement = component_value; - - component.className = 'satus-button'; - component_value.className = 'satus-color-picker__value'; - - component.appendChild(component_label); - component.appendChild(component_value); - - component.addEventListener('click', function () { - var rgb = this.rgb, - hsl = satus.color.rgbToHsl(rgb), - s = hsl[1] / 100, - l = hsl[2] / 100; - - s *= l < .5 ? l : 1 - l; - - var v = l + s; - - s = 2 * s / (l + s); - - satus.render({ - component: 'modal', - variant: 'color-picker', - value: hsl, - parent: this, - - palette: { - component: 'div', - class: 'satus-color-picker__palette', - style: { - 'backgroundColor': 'hsl(' + hsl[0] + 'deg, 100%, 50%)' - }, - on: { - mousedown: function () { - var palette = this, - rect = this.getBoundingClientRect(), - cursor = this.children[0]; - - function mousemove(event) { - var hsl = palette.skeleton.parent.value, - x = event.clientX - rect.left, - y = event.clientY - rect.top, - s; - - x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100); - y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100); - - var v = 100 - y, - l = (2 - x / 100) * v / 2; - - hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2); - hsl[2] = l; - - cursor.style.left = x + '%'; - cursor.style.top = y + '%'; - - palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; - - event.preventDefault(); - } - - function mouseup() { - window.removeEventListener('mousemove', mousemove); - window.removeEventListener('mouseup', mouseup); - } - - window.addEventListener('mousemove', mousemove); - window.addEventListener('mouseup', mouseup); - } - }, - - cursor: { - component: 'div', - class: 'satus-color-picker__cursor', - style: { - 'left': s * 100 + '%', - 'top': 100 - v * 100 + '%' - } - } - }, - section: { - component: 'section', - variant: 'color', - - color: { - component: 'div', - class: 'satus-color-picker__color', - style: { - 'backgroundColor': 'rgb(' + this.rgb.join(',') + ')' - } - }, - hue: { - component: 'slider', - class: 'satus-color-picker__hue', - storage: false, - value: hsl[0], - max: 360, - on: { - change: function () { - var modal = this.skeleton.parent.parent, - hsl = modal.value; - - hsl[0] = this.values[0]; - - this.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; - this.parentNode.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg, 100%, 50%)'; - } - } - } - }, - actions: { - component: 'section', - variant: 'actions', - - reset: { - component: 'button', - text: 'reset', - on: { - click: function () { - var modal = this.skeleton.parent.parent, - component = modal.parent; - - component.rgb = component.skeleton.value; - - component.storageValue = component.rgb; - component.storageChange(); - - component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; - - modal.rendered.close(); - } - } - }, - cancel: { - component: 'button', - text: 'cancel', - on: { - click: function () { - this.skeleton.parent.parent.rendered.close(); - } - } - }, - ok: { - component: 'button', - text: 'OK', - on: { - click: function () { - var modal = this.skeleton.parent.parent, - component = modal.parent; - - component.rgb = satus.color.hslToRgb(modal.value); - - component.storageValue = component.rgb; - component.storageChange(); - - component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; - - modal.rendered.close(); - } - } - } - } - }); - }); - - component.addEventListener('render', function () { - component.rgb = this.storageValue || [0, 100, 50]; - - component_value.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> TABS ---------------------------------------------------------------*/ - -satus.components.tabs = function (skeleton) { - var component = document.createElement('div'), - content = document.createElement('div'), - selection = document.createElement('div'); - - content.className = 'satus-tabs__content'; - selection.className = 'satus-tabs__selection'; - selection.style.width = 100 / skeleton.items.length + '%'; - - content.appendChild(selection); - - component.selection = selection; - - for (var i = 0, l = skeleton.items.length; i < l; i++) { - var item = skeleton.items[i], - button = document.createElement('button'); - - button.className = 'satus-tabs__button'; - button.value = item; - button.style.width = 100 / l + '%'; - - satus.text(button, item); - - button.addEventListener('click', function () { - var component = this.parentNode.parentNode; - - component.selection.style.left = 100 / (this.parentNode.children.length - 1) * (satus.indexOf(this) - 1) + '%'; - - component.storageValue = this.value; - component.storageChange(); - }); - - if (skeleton.value === item) { - selection.style.left = i * 50 + '%'; - } - - content.appendChild(button); - } - - component.appendChild(content); - - component.addEventListener('render', function () { - var index = satus.indexOf(this.storageValue, this.skeleton.items); - - if (index === -1) { - index = 0; - } - - this.selection.style.left = 100 / this.skeleton.items.length * index + '%'; - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> MENUBAR ---------------------------------------------------------------*/ - -satus.components.menubar = function (skeleton) { - var component = document.createElement('ul'); - - if (skeleton.items) { - for (var i = 0, l = skeleton.items.length; i < l; i++) { - var item = skeleton.items[i], - li = document.createElement('li'); - - if (Array.isArray(item) === true) { - var ul = document.createElement('ul'); - - satus.render(item[0], li); - - for (var j = 1, k = item.length; j < k; j++) { - var li2 = document.createElement('li'); - - satus.render(item[j], li2); - - ul.appendChild(li2); - } - - li.appendChild(ul); - } else { - satus.render(item, li); - } - - component.appendChild(li); - } - } - - return component; -}; -/*-------------------------------------------------------------- ->>> RADIO ---------------------------------------------------------------*/ - -satus.components.radio = function (skeleton) { - var component = document.createElement('label'), - content = document.createElement('span'), - radio = document.createElement('input'); - - component.inner = content; - - radio.type = 'radio'; - - if (skeleton.group) { - component.storage = skeleton.group; - radio.name = skeleton.group; - } - - if (skeleton.value) { - radio.value = skeleton.value; - } - - component.addEventListener('render', function () { - this.storageValue = satus.storage.get(this.storage); - - if (satus.isset(this.storageValue)) { - radio.checked = this.storageValue === skeleton.value; - } else if (skeleton.checked) { - radio.checked = true; - } - }); - - radio.addEventListener('change', function () { - component.storageValue = this.value; - component.storageChange(); - }); - - component.appendChild(content); - component.appendChild(radio); - - return component; -}; -/*-------------------------------------------------------------- ->>> LIST ---------------------------------------------------------------*/ - -satus.components.list = function (skeleton) { - var ul = document.createElement('ul'); - - for (var i = 0, l = skeleton.items.length; i < l; i++) { - var li = document.createElement('li'), - item = skeleton.items[i]; - - li.className = 'satus-list__item'; - - for (var j = 0, k = item.length; j < k; j++) { - var child = item[j]; - - if (typeof child === 'string') { - var span = document.createElement('span'); - - span.textContent = satus.locale.get(child); - - li.appendChild(span); - } else { - satus.render(child, li); - } - } - - ul.appendChild(li); - } - - return ul; -}; -/*-------------------------------------------------------------- ->>> MODAL ---------------------------------------------------------------*/ - -satus.components.modal = function (skeleton) { - var component = document.createElement('div'), - scrim = document.createElement('div'), - surface = document.createElement('div'); - - component.inner = surface; - - scrim.className = 'satus-modal__scrim'; - surface.className = 'satus-modal__surface'; - - component.close = function () { - var component = this, - component_surface = this.children[1]; - - this.classList.add('satus-modal--closing'); - - setTimeout(function () { - component.remove(); - - component.dispatchEvent(new CustomEvent('close')); - }, satus.getAnimationDuration(component_surface)); - }; - - scrim.addEventListener('click', function () { - this.parentNode.close(); - }); - - component.appendChild(scrim); - component.appendChild(surface); - - return component; -}; -/*-------------------------------------------------------------- ->>> CHECKBOX ---------------------------------------------------------------*/ - -satus.components.checkbox = function (skeleton) { - var component = document.createElement('button'), - content = document.createElement('span'); - - component.inner = content; - - content.className = 'satus-checkbox__content'; - - component.appendChild(content); - - component.addEventListener('click', function () { - if (this.dataset.value === 'true') { - this.storageValue = false; - this.dataset.value = 'false'; - } else { - this.storageValue = true; - this.dataset.value = 'true'; - } - - this.storageChange(); - }); - - component.addEventListener('render', function () { - this.dataset.value = this.storageValue; - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> SWITCH ---------------------------------------------------------------*/ - -satus.components.switch = function (skeleton) { - var component = document.createElement('button'), - component_content = document.createElement('span'), - component_thumb = document.createElement('i'); - - component.inner = component_content; - - component_content.className = 'satus-switch__content'; - - component.addEventListener('click', function () { - if (this.dataset.value === 'true') { - this.storageValue = false; - this.dataset.value = 'false'; - } else { - this.storageValue = true; - this.dataset.value = 'true'; - } - - this.storageChange(); - }); - - component.addEventListener('render', function () { - this.dataset.value = this.storageValue; - }); - - component.appendChild(component_content); - component.appendChild(component_thumb); - - return component; -}; -/*-------------------------------------------------------------- ->>> SLIDER ---------------------------------------------------------------*/ - -satus.components.slider = function (skeleton) { - var component = document.createElement('div'), - content = document.createElement('div'), - container = document.createElement('div'), - track = document.createElement('div'), - track_fill = document.createElement('div'); - - container.className = 'satus-slider__container'; - track.className = 'satus-slider__track'; - track_fill.className = 'satus-slider__track-fill'; - - component.min = skeleton.min || 0; - component.max = skeleton.max || 1; - component.step = (skeleton.step || 1); - component.percent = 100 / ((component.max - component.min) / component.step); - component.precision = String(component.step).replace(/[0-9]./, '').length; - - component.container = container; - component.track = track_fill; - component.handles = []; - component.inner = content; - - component.toPercent = function (number) { - return number / this.step * this.percent + '%'; - }; - - component.createHandle = function (index) { - var handle = document.createElement('div'); - - handle.className = 'satus-slider__handle'; - handle.handleIndex = index; - handle.tabIndex = 0; - - this.handles.push(handle); - - this.container.appendChild(handle); - }; - - component.update = function () { - if (this.values.length > 1) { - var min = Math.min.apply(null, this.values) - this.min, - max = Math.max.apply(null, this.values) - this.min; - - this.track.style.left = this.toPercent(min); - this.track.style.width = this.toPercent(max - min); - - for (var i = 0, l = this.handles.length; i < l; i++) { - var handle = this.handles[i], - value = this.values[i]; - - handle.style.left = this.toPercent(value - this.min); - handle.dataset.value = value; - } - } else { - var value = this.values[0]; - - this.track.style.width = this.toPercent(value - this.min); - this.handles[0].style.left = this.toPercent(value - this.min); - this.handles[0].dataset.value = value; - } - }; - - component.appendChild(content); - track.appendChild(track_fill); - container.appendChild(track); - component.appendChild(container); - - component.addEventListener('keydown', function (event) { - var code = event.keyCode; - - console.log(code); - }); - - component.addEventListener('render', function () { - var value = this.storageValue; - - if (satus.isArray(value)) { - this.values = value; - } else if (satus.isNumber(value)) { - this.values = [value]; - } else { - this.values = this.skeleton.values || [satus.isset(this.skeleton.value) ? this.skeleton.value : 1]; - } - - for (var i = 0, l = this.values.length; i < l; i++) { - this.createHandle(i); - } - - this.update(); - }); - - container.addEventListener('mousedown', function (event) { - if (event.button === 0) { - var component = this.parentNode, - rect = this.getBoundingClientRect(), - cursor_x = event.clientX - rect.left, - percent = cursor_x / rect.width * 100, - steps = percent / component.percent * component.step + component.min, - closest_value = component.values.indexOf(component.values.reduce(function(previous, current, index) { - return Math.abs(current - steps) < Math.abs(previous - steps) ? current : previous; - })), - handle_index = component.handles[closest_value].handleIndex; - - setTimeout(function () { - component.handles[closest_value].focus(); - }); - - function update(event) { - var cursor_x = Math.min(Math.max(event.clientX - rect.left, 0), rect.width), - percent = cursor_x / rect.width * 100, - value = percent / component.percent * component.step + component.min; - - value = (Math.round(value / component.step) * component.step); - - value = Number(value.toFixed(component.precision)); - - if (component.values[handle_index] !== value) { - component.values[handle_index] = value; - - component.storageValue = component.values.length === 1 ? component.values[0] : component.values; - - component.storageChange(); - } - - component.update(); - } - - function mousemove(event) { - update(event); - } - - function mouseup(event) { - window.removeEventListener('mousemove', mousemove); - window.removeEventListener('mouseup', mouseup); - }; - - window.addEventListener('mousemove', mousemove); - window.addEventListener('mouseup', mouseup); - - update(event); - - return true; - } - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> SHORTCUT ---------------------------------------------------------------*/ - -satus.components.shortcut = function (skeleton) { - var component = document.createElement('button'), - content = document.createElement('span'), - value = document.createElement('div'); - - component.inner = content; - - component.className = 'satus-button'; - value.className = 'satus-shortcut__value'; - - component.update = function () { - var object = satus.storage.get(this.skeleton.storage) || this.skeleton.value || {}, - array = []; - - if (object.shift) { - array.push('Shift'); - } - - if (object.ctrl) { - array.push('Ctrl'); - } - - if (object.alt) { - array.push('Alt'); - } - - if (typeof object.keys === 'object') { - for (var key in object.keys) { - var char = object.keys[key].key || object.keys[key].code; - - if (key === 32) { - char = 'space'; - } - - array.push(char); - } - } - - this.valueElement.textContent = array.join(' + '); - }; - - component.render = function () { - var self = this, - children = this.primary.children; - - satus.empty(this.primary); - - function createElement(name) { - var element = document.createElement('div'); - - element.className = 'satus-shortcut__' + name; - - self.primary.appendChild(element); - - return element; - } - - if (this.data.alt) { - createElement('key').textContent = 'Alt'; - } - - if (this.data.ctrl) { - if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { - createElement('plus'); - } - - createElement('key').textContent = 'Ctrl'; - } - - if (this.data.shift) { - if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { - createElement('plus'); - } - - createElement('key').textContent = 'Shift'; - } - - for (var code in this.data.keys) { - if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { - createElement('plus'); - } - - createElement('key').textContent = this.data.keys[code].key.toUpperCase(); - } - - if (this.data.wheel) { - if (children.length && children[children.length - 1].className.indexOf('key') !== -1) { - createElement('plus'); - } - - var mouse = createElement('mouse'), - div = document.createElement('div'); - - mouse.appendChild(div); - - mouse.className += ' ' + (this.data.wheel > 0); - } - }; - - component.valueElement = value; - - component.appendChild(content); - component.appendChild(value); - - component.keydown = function (event) { - event.preventDefault(); - event.stopPropagation(); - - component.data = { - alt: event.altKey, - ctrl: event.ctrlKey, - shift: event.shiftKey, - keys: {} - }; - - if (['control', 'alt', 'altgraph', 'shift'].indexOf(event.key.toLowerCase()) === -1) { - component.data.keys[event.keyCode] = { - code: event.code, - key: event.key - }; - } - - component.data.wheel = 0; - - component.render(); - - return false; - }; - - component.mousewheel = function (event) { - event.stopPropagation(); - - if ( - ( - component.data.wheel === 0 && - ( - Object.keys(component.data.keys).length === 0 && - component.data.alt === false && - component.data.ctrl === false && - component.data.shift === false - ) - ) || - component.data.wheel < 0 && event.deltaY > 0 || - component.data.wheel > 0 && event.deltaY < 0) { - component.data = { - alt: false, - ctrl: false, - shift: false, - keys: {} - }; - } - - component.data.wheel = event.deltaY < 0 ? -1 : 1; - - component.render(); - - return false; - }; - - component.addEventListener('render', function () { - this.data = this.storageValue || { - alt: false, - ctrl: false, - shift: false, - keys: {}, - wheel: 0 - }; - - this.update(); - }); - - component.addEventListener('click', function () { - satus.render({ - component: 'modal', - on: { - close: function () { - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('mousewheel', component.mousewheel); - } - }, - - primary: { - component: 'div', - class: 'satus-shortcut__primary', - on: { - render: function () { - component.primary = this; - - component.render(); - } - } - }, - actions: { - component: 'section', - variant: 'actions', - - reset: { - component: 'button', - text: 'reset', - on: { - click: function () { - component.data = component.skeleton.value; - - component.update(); - - satus.storage.set(skeleton.storage, false); - - this.parentNode.parentNode.parentNode.close(); - - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('mousewheel', component.mousewheel); - } - } - }, - cancel: { - component: 'button', - text: 'cancel', - on: { - click: function () { - component.data = satus.storage.get(component.storage) || component.skeleton.value; - - component.update(); - - this.parentNode.parentNode.parentNode.close(); - - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('mousewheel', component.mousewheel); - } - } - }, - save: { - component: 'button', - text: 'save', - on: { - click: function () { - component.storageValue = component.data; - - component.storageChange(); - - component.update(); - - this.parentNode.parentNode.parentNode.close(); - - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('mousewheel', component.mousewheel); - } - } - } - } - }); - - window.addEventListener('keydown', this.keydown); - window.addEventListener('mousewheel', this.mousewheel); - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> BASE ---------------------------------------------------------------*/ - -satus.components.base = function (skeleton) { - var component = document.createElement('div'); - - component.base = component; - - return component; -}; -/*-------------------------------------------------------------- ->>> TEXT FIELD ---------------------------------------------------------------*/ - -satus.components.textField = function (skeleton) { - var component = document.createElement('div'), - pre = document.createElement('pre'), - input = document.createElement('textarea'), - hidden_text = document.createElement('span'), - text = document.createElement('span'), - selection = document.createElement('div'), - cursor = document.createElement('div'); - - input.className = 'satus-text-field__input'; - pre.className = 'satus-text-field__pre'; - hidden_text.className = 'satus-text-field__hidden-text'; - text.className = 'satus-text-field__text'; - selection.className = 'satus-text-field__selection'; - cursor.className = 'satus-text-field__cursor'; - - component.inputElement = input; - component.textElement = text; - component.languages = { - regex: function (component) { - var regex_token = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, - char_class_token = /[^\\-]+|-|\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)/g, - char_class_parts = /^(\[\^?)(]?(?:[^\\\]]+|\\[\S\s]?)*)(]?)$/, - quantifier = /^(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??$/, - matches = component.inputElement.value.match(regex_token); - - function create(type, string) { - var span = document.createElement('span'); - - span.className = type; - span.textContent = string; - - component.textElement.appendChild(span); - } - - for (var i = 0, l = matches.length; i < l; i++) { - var match = matches[i]; - - if (match[0] === '[') { - create('character-class', match); - } else if (match[0] === '(') { - create('group', match); - } else if (match[0] === ')') { - create('group', match); - } else if (match[0] === '\\' || match === '^') { - create('anchor', match); - } else if (quantifier.test(match)) { - create('quantifier', match); - } else if (match === '|' || match === '.') { - create('metasequence', match); - } else { - create('text', match); - } - } - } - }; - component._syntax = skeleton.syntax; - - Object.defineProperty(component, 'value', { - get: function () { - return this.inputElement.value; - }, - set: function (value) { - var input = this.inputElement; - - input.value = value; - - input.updateValue(); - input.updateCursor(); - } - }); - - Object.defineProperty(component, 'syntax', { - get: function () { - return this._syntax; - }, - set: function (value) { - var input = this.inputElement; - - this._syntax = value; - - input.updateValue(); - input.updateCursor(); - } - }); - - input.rows = skeleton.rows || 1; - input.autocapitalize = 'none'; - input.autocomplete = 'off'; - input.autocorrect = 'off'; - input.spellcheck = false; - input.autofocus = true; - input.textElement = text; - input.hiddenTextElement = hidden_text; - input.selectionElement = selection; - input.cursorElement = cursor; - - input.updateValue = function () { - var component = this.parentNode.parentNode; - - for (var i = this.textElement.childNodes.length - 1; i > -1; i--) { - this.textElement.childNodes[i].remove(); - } - - if (this.value.length > 0) { - if (component.languages[component._syntax]) { - component.languages[component._syntax](component); - } else { - this.textElement.textContent = this.value; - } - } - }; - - input.updateCursor = function () { - var cursor = this.cursorElement, - selection = this.selectionElement, - hidden_text = this.hiddenTextElement, - start = this.selectionStart, - end = this.selectionEnd; - - cursor.style.animation = 'none'; - - if (start === end) { - selection.setAttribute('disabled', ''); - } else { - selection.removeAttribute('disabled'); - - hidden_text.textContent = this.value.substring(0, start); - - selection.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px'; - - hidden_text.textContent = this.value.substring(start, end); - - selection.style.width = hidden_text.offsetWidth + 'px'; - } - - if (this.selectionDirection === 'forward') { - hidden_text.textContent = this.value.substring(0, end); - } else { - hidden_text.textContent = this.value.substring(0, start); - } - - cursor.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px'; - - cursor.style.animation = ''; - - hidden_text.textContent = ''; - }; - - input.addEventListener('keydown', function () { - var self = this; - - setTimeout(function () { - var component = self.parentNode.parentNode; - - component.storageValue = self.value; - component.storageChange(); - - self.updateValue(); - self.updateCursor(); - }); - }); - - input.addEventListener('scroll', function (event) { - this.textElement.style.left = -this.scrollLeft + 'px'; - }); - - document.addEventListener('selectionchange', function () { - input.updateCursor(); - }); - - selection.setAttribute('disabled', ''); - - pre.appendChild(input); - pre.appendChild(hidden_text); - pre.appendChild(text); - pre.appendChild(selection); - pre.appendChild(cursor); - component.appendChild(pre); - - component.addEventListener('render', function () { - input.value = this.storageValue; - - this.inputElement.updateValue(); - this.inputElement.updateCursor(); - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> ALERT ---------------------------------------------------------------*/ - -satus.components.alert = function (skeleton) { - var component = document.createElement('div'); - - return component; -}; -/*-------------------------------------------------------------- ->>> LAYERS ---------------------------------------------------------------*/ - -satus.components.layers = function (skeleton) { - var component = document.createElement('div'); - - component.path = [skeleton]; - - component.back = function () { - if (this.path.length > 1) { - this.path.pop(); - - this.open(); - } - }; - - component.open = function (skeleton) { - var layer = document.createElement('div'); - - if (skeleton) { - this.path.push(skeleton); - } else { - skeleton = this.path[this.path.length - 1]; - } - - layer.className = 'satus-layer'; - - layer.skeleton = skeleton; - layer.base = this.base; - - satus.render(skeleton, layer, skeleton.component === 'layers'); - - satus.empty(this); - - this.appendChild(layer); - - this.dispatchEvent(new Event('open')); - }; - - component.update = function () { - var layer = this.querySelector('.satus-layer'); - - satus.empty(layer); - - satus.render(layer.skeleton, layer); - }; - - component.render_children = false; - - component.addEventListener('render', function () { - this.open(); - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> DIVIDER ---------------------------------------------------------------*/ - -satus.components.divider = function () { - var component = document.createElement('div'); - - return component; -}; -/*-------------------------------------------------------------- ->>> INPUT ---------------------------------------------------------------*/ - -satus.components.input = function (skeleton) { - var component = document.createElement('input'); - - if (skeleton.attr) { - var key = skeleton.attr.name || skeleton.storage, - value; - - if (satus.isset(satus.storage.get(key))) { - value = satus.storage.get(key); - } else { - value = skeleton.value; - } - - if (skeleton.attr.type === 'radio') { - component.checked = value === skeleton.attr.value || skeleton.value; - } else if (satus.isset(value)) { - component.value = value; - } - - component.addEventListener('change', function () { - var key = this.skeleton.attr.name || this.skeleton.storage; - - satus.storage.set(key, this.value); - }); - } else { - var key = skeleton.name || skeleton.storage, - value; - - component.type = skeleton.type; - - if (satus.isset(satus.storage.get(key))) { - value = satus.storage.get(key); - } else { - value = skeleton.value; - } - - if (skeleton.type === 'radio') { - component.checked = value === skeleton.value || skeleton.value; - } else if (satus.isset(value)) { - component.value = value; - } - - component.addEventListener('change', function () { - var key = this.skeleton.name || this.skeleton.storage; - - satus.storage.set(key, this.value); - }); - } - - return component; -}; -/*-------------------------------------------------------------- ->>> SELECT ---------------------------------------------------------------*/ - -satus.components.select = function (skeleton) { - var component = document.createElement('div'), - component_content = document.createElement('span'), - component_value = document.createElement('span'), - select = document.createElement('select'); - - component_content.className = 'satus-select__content'; - component_value.className = 'satus-select__value'; - - for (var i = 0, l = skeleton.options.length; i < l; i++) { - var option = document.createElement('option'); - - option.value = skeleton.options[i].value; - - satus.text(option, skeleton.options[i].text); - - select.appendChild(option); - } - - component.selectElement = select; - select.valueElement = component_value; - - select.addEventListener('change', function () { - satus.empty(this.valueElement); - - satus.text(this.valueElement, this.options[this.selectedIndex].text); - - this.parentNode.storageValue = this.value; - - this.parentNode.storageChange(); - }); - - component.appendChild(component_content); - component.appendChild(component_value); - component.appendChild(select); - - component.addEventListener('render', function () { - select.value = this.storageValue || this.skeleton.options[0].value; - - satus.text(select.valueElement, select.options[select.selectedIndex].text); - }); - - component.inner = component_content; - - return component; -}; -/*-------------------------------------------------------------- ->>> COLOR: ----------------------------------------------------------------- -# RGB to HSL -# HUE to RGB -# HSL to RGB ---------------------------------------------------------------*/ - -satus.color = {}; - - -/*-------------------------------------------------------------- -# RGB TO HSL ---------------------------------------------------------------*/ - -satus.color.rgbToHsl = function (array) { - var r = array[0] / 255, - g = array[1] / 255, - b = array[2] / 255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - h = 0, - s = 0, - l = (min + max) / 2; - - if (min === max) { - h = 0; - s = 0; - } else { - var delta = max - min; - - s = l <= 0.5 ? delta / (max + min) : delta / (2 - max - min); - - if (max === r) { - h = (g - b) / delta + (g < b ? 6 : 0); - } else if (max === g) { - h = (b - r) / delta + 2; - } else if (max === b) { - h = (r - g) / delta + 4; - } - - h /= 6; - } - - h *= 360; - s *= 100; - l *= 100; - - if (array.length === 3) { - return [h, s, l]; - } else { - return [h, s, l, array[3]]; - } -}; - - -/*-------------------------------------------------------------- -# HUE TO RGB ---------------------------------------------------------------*/ - -satus.color.hueToRgb = function (array) { - var t1 = array[0], - t2 = array[1], - hue = array[2]; - - if (hue < 0) { - hue += 6; - } - - if (hue >= 6) { - hue -= 6; - } - - if (hue < 1) { - return (t2 - t1) * hue + t1; - } else if (hue < 3) { - return t2; - } else if (hue < 4) { - return (t2 - t1) * (4 - hue) + t1; - } else { - return t1; - } -}; - - -/*-------------------------------------------------------------- -# HSL TO RGB ---------------------------------------------------------------*/ - -satus.color.hslToRgb = function (array) { - var h = array[0] / 360, - s = array[1] / 100, - l = array[2] / 100, - r, g, b; - - if (s == 0) { - r = g = b = l; - } else { - var hue2rgb = function hue2rgb(p, q, t) { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6) return p + (q - p) * 6 * t; - if (t < 1 / 2) return q; - if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; - return p; - } - - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1 / 3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1 / 3); - } - - return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; -}; -/*-------------------------------------------------------------- ->>> USER ---------------------------------------------------------------*/ - -satus.user = function () { - /*-------------------------------------------------------------- - 1.0 VARIABLES - --------------------------------------------------------------*/ - - var user_agent = navigator.userAgent, - random_cookie = 'ta{t`nX6cMXK,Wsc', - video = document.createElement('video'), - video_formats = { - ogg: 'video/ogg; codecs="theora"', - h264: 'video/mp4; codecs="avc1.42E01E"', - webm: 'video/webm; codecs="vp8, vorbis"', - vp9: 'video/webm; codecs="vp9"', - hls: 'application/x-mpegURL; codecs="avc1.42E01E"' - }, - audio = document.createElement('audio'), - audio_formats = { - mp3: 'audio/mpeg', - mp4: 'audio/mp4', - aif: 'audio/x-aiff' - }, - cvs = document.createElement('canvas'), - ctx = cvs.getContext('webgl'), - data = { - browser: { - audio: null, - cookies: null, - flash: null, - java: null, - languages: null, - name: null, - platform: null, - version: null, - video: null, - webgl: null - }, - os: { - name: null, - type: null - }, - device: { - connection: { - type: null, - speed: null - }, - cores: null, - gpu: null, - max_touch_points: null, - ram: null, - screen: null, - touch: null - } - }; - - - /*-------------------------------------------------------------- - 2.0 SOFTWARE - --------------------------------------------------------------*/ - - /*-------------------------------------------------------------- - 2.1.0 OS - --------------------------------------------------------------*/ - - /*-------------------------------------------------------------- - 2.1.1 NAME - --------------------------------------------------------------*/ - - if (navigator.appVersion.indexOf('Win') !== -1) { - if (navigator.appVersion.match(/(Windows 10.0|Windows NT 10.0)/)) { - data.os.name = 'Windows 10'; - } else if (navigator.appVersion.match(/(Windows 8.1|Windows NT 6.3)/)) { - data.os.name = 'Windows 8.1'; - } else if (navigator.appVersion.match(/(Windows 8|Windows NT 6.2)/)) { - data.os.name = 'Windows 8'; - } else if (navigator.appVersion.match(/(Windows 7|Windows NT 6.1)/)) { - data.os.name = 'Windows 7'; - } else if (navigator.appVersion.match(/(Windows NT 6.0)/)) { - data.os.name = 'Windows Vista'; - } else if (navigator.appVersion.match(/(Windows NT 5.1|Windows XP)/)) { - data.os.name = 'Windows XP'; - } else { - data.os.name = 'Windows'; - } - } else if (navigator.appVersion.indexOf('(iPhone|iPad|iPod)') !== -1) { - data.os.name = 'iOS'; - } else if (navigator.appVersion.indexOf('Mac') !== -1) { - data.os.name = 'macOS'; - } else if (navigator.appVersion.indexOf('Android') !== -1) { - data.os.name = 'Android'; - } else if (navigator.appVersion.indexOf('OpenBSD') !== -1) { - data.os.name = 'OpenBSD'; - } else if (navigator.appVersion.indexOf('SunOS') !== -1) { - data.os.name = 'SunOS'; - } else if (navigator.appVersion.indexOf('Linux') !== -1) { - data.os.name = 'Linux'; - } else if (navigator.appVersion.indexOf('X11') !== -1) { - data.os.name = 'UNIX'; - } - - /*-------------------------------------------------------------- - 2.1.2 TYPE - --------------------------------------------------------------*/ - - if (navigator.appVersion.match(/(Win64|x64|x86_64|WOW64)/)) { - data.os.type = '64-bit'; - } else { - data.os.type = '32-bit'; - } - - - /*-------------------------------------------------------------- - 2.2.0 BROWSER - --------------------------------------------------------------*/ - - /*-------------------------------------------------------------- - 2.2.1 NAME - --------------------------------------------------------------*/ - - if (user_agent.indexOf('Opera') !== -1) { - data.browser.name = 'Opera'; - } else if (user_agent.indexOf('Vivaldi') !== -1) { - data.browser.name = 'Vivaldi'; - } else if (user_agent.indexOf('Edge') !== -1) { - data.browser.name = 'Edge'; - } else if (user_agent.indexOf('Chrome') !== -1) { - data.browser.name = 'Chrome'; - } else if (user_agent.indexOf('Safari') !== -1) { - data.browser.name = 'Safari'; - } else if (user_agent.indexOf('Firefox') !== -1) { - data.browser.name = 'Firefox'; - } else if (user_agent.indexOf('MSIE') !== -1) { - data.browser.name = 'IE'; - } - - - /*-------------------------------------------------------------- - 2.2.2 VERSION - --------------------------------------------------------------*/ - - var browser_version = user_agent.match(new RegExp(data.browser.name + '/([0-9.]+)')); - - if (browser_version[1]) { - data.browser.version = browser_version[1]; - } - - - /*-------------------------------------------------------------- - 2.2.3 PLATFORM - --------------------------------------------------------------*/ - - data.browser.platform = navigator.platform || null; - - - /*-------------------------------------------------------------- - 2.2.4 LANGUAGES - --------------------------------------------------------------*/ - - data.browser.languages = navigator.languages || null; - - - /*-------------------------------------------------------------- - 2.2.5 COOKIES - --------------------------------------------------------------*/ - - if (document.cookie) { - document.cookie = random_cookie; - - if (document.cookie.indexOf(random_cookie) !== -1) { - data.browser.cookies = true; - } - } - - - /*-------------------------------------------------------------- - 2.2.6 FLASH - --------------------------------------------------------------*/ - - try { - if (new ActiveXObject('ShockwaveFlash.ShockwaveFlash')) { - data.browser.flash = true; - } - } catch (e) { - if (navigator.mimeTypes['application/x-shockwave-flash']) { - data.browser.flash = true; - } - } - - - /*-------------------------------------------------------------- - 2.2.7 JAVA - --------------------------------------------------------------*/ - - if (typeof navigator.javaEnabled === 'function' && navigator.javaEnabled()) { - data.browser.java = true; - } - - - /*-------------------------------------------------------------- - 2.2.8 VIDEO FORMATS - --------------------------------------------------------------*/ - - if (typeof video.canPlayType === 'function') { - data.browser.video = {}; - - for (var i in video_formats) { - var can_play_type = video.canPlayType(video_formats[i]); - - if (can_play_type === '') { - data.browser.video[i] = false; - } else { - data.browser.video[i] = can_play_type; - } - } - } - - - /*-------------------------------------------------------------- - 2.2.9 AUDIO FORMATS - --------------------------------------------------------------*/ - - if (typeof audio.canPlayType === 'function') { - data.browser.audio = {}; - - for (var i in audio_formats) { - var can_play_type = audio.canPlayType(audio_formats[i]); - - if (can_play_type == '') { - data.browser.audio[i] = false; - } else { - data.browser.audio[i] = can_play_type; - } - } - } - - - /*-------------------------------------------------------------- - 2.2.10 WEBGL - --------------------------------------------------------------*/ - - if (ctx && ctx instanceof WebGLRenderingContext) { - data.browser.webgl = true; - } - - - /*-------------------------------------------------------------- - 3.0 HARDWARE - --------------------------------------------------------------*/ - - /*-------------------------------------------------------------- - 3.1 SCREEN - --------------------------------------------------------------*/ - - if (screen) { - data.device.screen = screen.width + 'x' + screen.height; - } - - - /*-------------------------------------------------------------- - 3.2 RAM - --------------------------------------------------------------*/ - - if ('deviceMemory' in navigator) { - data.device.ram = navigator.deviceMemory + ' GB'; - } - - - /*-------------------------------------------------------------- - 3.3 GPU - --------------------------------------------------------------*/ - - if ( - ctx && - ctx instanceof WebGLRenderingContext && - 'getParameter' in ctx && - 'getExtension' in ctx - ) { - var info = ctx.getExtension('WEBGL_debug_renderer_info'); - - if (info) { - data.device.gpu = ctx.getParameter(info.UNMASKED_RENDERER_WEBGL); - } - } - - - /*-------------------------------------------------------------- - 3.4 CORES - --------------------------------------------------------------*/ - - if (navigator.hardwareConcurrency) { - data.device.cores = navigator.hardwareConcurrency; - } - - - /*-------------------------------------------------------------- - 3.5 TOUCH - --------------------------------------------------------------*/ - - if ( - window.hasOwnProperty('ontouchstart') || - window.DocumentTouch && document instanceof window.DocumentTouch || - navigator.maxTouchPoints > 0 || - window.navigator.msMaxTouchPoints > 0 - ) { - data.device.touch = true; - data.device.max_touch_points = navigator.maxTouchPoints; - } - - - /*-------------------------------------------------------------- - 3.6 CONNECTION - --------------------------------------------------------------*/ - - if (typeof navigator.connection === 'object') { - data.device.connection.type = navigator.connection.effectiveType || null; - - if (navigator.connection.downlink) { - data.device.connection.speed = navigator.connection.downlink + ' Mbps'; - } - } - - - /*-------------------------------------------------------------- - 4.0 CLEARING - --------------------------------------------------------------*/ - - video.remove(); - audio.remove(); - cvs.remove(); - - - return data; -}; -/*-------------------------------------------------------------- ->>> CONTEXT MENU ---------------------------------------------------------------*/ - -satus.events.add('render', function (component, skeleton) { - if (skeleton.contextMenu) { - component.addEventListener('contextmenu', function (event) { - var x = event.clientX, - y = event.clientY, - modal = satus.render({ - component: 'modal', - variant: 'contextmenu', - parent: skeleton - }); - - if (window.innerWidth - x < 200) { - x = window.innerWidth - 200; - } - - modal.inner.style.left = x + 'px'; - modal.inner.style.top = y + 'px'; - - satus.render(skeleton.contextMenu, modal.inner); - - event.preventDefault(); - event.stopPropagation(); - - return false; - }); - } -}); -/*-------------------------------------------------------------- ->>> EXTENSION STORAGE ---------------------------------------------------------------*/ -/*-------------------------------------------------------------- ->>> PLUVIAM ---------------------------------------------------------------*/ - -satus.events.add('render', function (component, skeleton) { - if (skeleton.pluviam === true) { - function createPluviam(event) { - var pluviam = document.createElement('span'), - rect = this.getBoundingClientRect(), - x = event.clientX - rect.left, - y = event.clientY - rect.top, - diameter = Math.sqrt(Math.pow(rect.width * 2, 2) + Math.pow(rect.height * 2, 2)); - - pluviam.className = 'satus-pluviam'; - - pluviam.style.left = x - diameter / 2 + 'px'; - pluviam.style.top = y - diameter / 2 + 'px'; - pluviam.style.width = diameter + 'px'; - pluviam.style.height = diameter + 'px'; - - this.appendChild(pluviam); - - setTimeout(function () { - pluviam.remove(); - }, 1000); - } - - component.addEventListener('mousedown', createPluviam); - component.addEventListener('mouseover', createPluviam); - } -}); -/*-------------------------------------------------------------- ->>> SORTABLE ---------------------------------------------------------------*/ - -satus.events.add('render', function (component, skeleton) { - if (skeleton.sortable === true) { - component.addEventListener('mousedown', function (event) { - if (event.button !== 0) { - return false; - } - - var component = this, - rect = this.getBoundingClientRect(), - x = event.clientX, - y = event.clientY, - offset_x = event.clientX - rect.left, - offset_y = event.clientY - rect.top, - ghost = satus.clone(this), - children = this.parentNode.children, - appended = false; - - ghost.classList.add('satus-sortable__ghost'); - - function mousemove(event) { - if (appended === false && (Math.abs(event.clientX - x) > 4 || Math.abs(event.clientY - y) > 4)) { - appended = true; - - component.classList.add('satus-sortable__chosen'); - - component.parentNode.appendChild(ghost); - } - - ghost.style.transform = 'translate(' + (event.clientX - offset_x) + 'px, ' + (event.clientY - offset_y) + 'px)'; - } - - function mouseup(event) { - component.classList.remove('satus-sortable__chosen'); - ghost.remove(); - - window.removeEventListener('mousemove', mousemove, true); - window.removeEventListener('mouseup', mouseup, true); - - for (var i = 0, l = children.length; i < l; i++) { - var child = children[i]; - - if (child !== component) { - child.removeEventListener('mouseover', siblingMouseOver); - } - } - - component.dispatchEvent(new CustomEvent('sort')); - - event.stopPropagation(); - - return false; - } - - window.addEventListener('mousemove', mousemove, { - passive: true, - capture: true - }); - - window.addEventListener('mouseup', mouseup, { - passive: true, - capture: true - }); - - function siblingMouseOver(event) { - var target = event.target, - parent = target.parentNode, - y = event.layerY / (target.offsetHeight / 100); - - if (y < 50 && target.previousSibling !== component || y >= 50 && target.nextSibling === component) { - parent.insertBefore(component, target); - } else { - parent.insertBefore(component, target.nextSibling); - } - } - - for (var i = 0, l = children.length; i < l; i++) { - var child = children[i]; - - if (child !== component) { - child.addEventListener('mouseover', siblingMouseOver); - } - } - - event.stopPropagation(); - event.preventDefault(); - - return false; - }); - } -}); \ No newline at end of file +var satus={components:{},events:{},locale:{strings:{}},storage:{attributes:{},data:{}},append:function(e,t){(t||document.body).appendChild(e)},getAnimationDuration:function(e){return 1e3*Number(window.getComputedStyle(e).getPropertyValue("animation-duration").replace(/[^0-9.]/g,""))},attr:function(e,t){if(t)for(var n in t){var a;e.is_svg?e.setAttributeNS(null,n,t[n]):(a=t[n],-1!==["placeholder","title"].indexOf(n)&&(a=satus.locale.get(a)),e.setAttribute(n,a))}},elementIndex:function(e){return Array.prototype.slice.call(e.parentNode.children).indexOf(e)},data:function(e,t){if(t)for(var n in t)e.dataset[n]=t[n]},properties:function(e,t){if(t)for(var n in t)e[n]=t[n]},camelize:function(e){for(var t="",n=0,a=e.length;nparseInt(e,16)),a={name:"AES-GCM",iv:new Uint8Array(n)};try{var s=(new TextDecoder).decode(await crypto.subtle.decrypt(a,await crypto.subtle.importKey("raw",await crypto.subtle.digest("SHA-256",(new TextEncoder).encode(t)),a,!1,["decrypt"]),new Uint8Array(atob(e.slice(24)).match(/[\s\S]/g).map(e=>e.charCodeAt(0)))))}catch(e){return!1}return s},satus.encrypt=async function(e,t){var n=crypto.getRandomValues(new Uint8Array(12)),a={name:"AES-GCM",iv:n};return Array.from(n).map(e=>("00"+e.toString(16)).slice(-2)).join("")+btoa(Array.from(new Uint8Array(await crypto.subtle.encrypt(a,await crypto.subtle.importKey("raw",await crypto.subtle.digest("SHA-256",(new TextEncoder).encode(t)),a,!1,["encrypt"]),(new TextEncoder).encode(e)))).map(e=>String.fromCharCode(e)).join(""))},satus.isArray=function(e){return!!Array.isArray(e)},satus.isNumber=function(e){return"number"==typeof e&&!1===isNaN(e)},satus.indexOf=function(e,t){var n=0;if(satus.isArray(t))n=t.indexOf(e);else for(;e=e.previousElementSibling;)n++;return n},satus.toIndex=function(e,t,n){satus.isArray(n)&&n.splice(e,0,n.splice(satus.indexOf(t,n),1)[0])},satus.clone=function(e){for(var t=e.cloneNode(!0),n=window.getComputedStyle(e.parentNode),a=window.getComputedStyle(e),s="",o=0,r=a.length;o .satus-shortcut { +.satus-section--row>.satus-shortcut { width: 100%; } @@ -123,9 +124,12 @@ body[theme=black] { border-radius: 50%; } -.satus-shortcut:hover + .satus-button--remove, -.satus-button--remove:hover -{ +.satus-shortcut > span:first-child { + display: none; +} + +.satus-shortcut:hover+.satus-button--remove, +.satus-button--remove:hover { visibility: visible; }