diff --git a/public/picker.js b/public/picker.js deleted file mode 100644 index 1f81e85..0000000 --- a/public/picker.js +++ /dev/null @@ -1,505 +0,0 @@ -var FwColourPicker = function(callback, options, colour, onClose) { - if(typeof callback !== 'function') - return; - if(typeof colour !== 'number') - colour = parseInt(colour || 0); - if(typeof options !== 'object') - options = {}; - - var readThres = 168, - lumiRed = .299, - lumiGreen = .587, - lumiBlue = .114; - - var extractRGB = function(raw) { - return [ - (raw >> 16) & 0xFF, - (raw >> 8) & 0xFF, - raw & 0xFF, - ]; - }; - - var calcLumi = function(raw) { - var rgb = extractRGB(raw); - return rgb[0] * lumiRed - + rgb[1] * lumiGreen - + rgb[2] * lumiBlue; - }; - - var textColour = function(raw) { - return calcLumi(raw) > readThres ? 0 : 0xFFFFFF; - }; - - var weightNum = function(n1, n2, w) { - w = Math.min(1, Math.max(0, w)); - return Math.round((n1 * w) + (n2 * (1 - w))); - }; - - var weightColour = function(c1, c2, w) { - c1 = extractRGB(c1); - c2 = extractRGB(c2); - return (weightNum(c1[0], c2[0], w) << 16) - | (weightNum(c1[1], c2[1], w) << 8) - | weightNum(c1[2], c2[2], w); - }; - - var shadeColour = function(raw, offset) { - if(offset == 0) - return raw; - - var dir = 0xFFFFFF; - if(offset < 0) { - dir = 0; - offset *= -1; - } - - return weightColour(dir, raw, offset); - }; - - var hexFormat = FwColourPicker.hexFormat; - - var verifyOption = function(name, type, def) { - if(typeof options[name] !== type) - options[name] = def; - }; - - verifyOption('posX', 'number', -1); - verifyOption('posY', 'number', -1); - verifyOption('presets', 'object', []); - verifyOption('showPresetsTab', 'boolean', options.presets.length > 0); - verifyOption('showGridTab', 'boolean', true); - verifyOption('showSlidersTab', 'boolean', true); - verifyOption('showHexValue', 'boolean', true); - verifyOption('showRawValue', 'boolean', true); - verifyOption('autoClose', 'boolean', true); - - var onColourChange = []; - var runOnColourChange = function() { - var text = textColour(colour); - for(var i = 0; i < onColourChange.length; ++i) - onColourChange[i](colour, text); - }; - - var setColour = function(raw) { - colour = parseInt(raw || 0) & 0xFFFFFF; - runOnColourChange(); - }; - - var apply = function() { - callback(pub, colour); - if(options.autoClose) - close(); - }; - - var cancel = function() { - callback(pub, null); - if(options.autoClose) - close(); - }; - - var close = function() { - if(onClose && onClose()) - return; - container.parentNode.removeChild(container); - }; - - var height = 96; - - var container = document.createElement('div'); - container.className = 'fw-colour-picker'; - onColourChange.push(function(colour) { - container.style.borderColor = hexFormat(colour); - }); - - var form = document.createElement('form'); - form.className = 'fw-colour-picker-form'; - container.appendChild(form); - - form.onsubmit = function(ev) { - ev.preventDefault(); - apply(); - return false; - }; - - var tabs = {}; - var activeTab = undefined; - onColourChange.push(function(colour, text) { - if(activeTab) { - activeTab.b.style.background = hexFormat(colour); - activeTab.b.style.borderColor = hexFormat(colour); - activeTab.b.style.color = hexFormat(text); - } - }); - - var tabbed = document.createElement('div'); - tabbed.className = 'fw-colour-picker-tabbed'; - - var tabbedContainer = document.createElement('div'); - tabbedContainer.className = 'fw-colour-picker-tabbed-container'; - tabbed.appendChild(tabbedContainer); - onColourChange.push(function(colour) { - tabbedContainer.style.borderColor = hexFormat(colour); - }); - - var tabbedList = document.createElement('div'); - tabbedList.className = 'fw-colour-picker-tabbed-list'; - tabbed.appendChild(tabbedList); - - var switchTab = function(id) { - if(activeTab == tabs[id]) - return; - - if(activeTab) { - activeTab.c.classList.remove('fw-colour-picker-tab-container-active'); - activeTab.b.classList.remove('fw-colour-picker-tab-button-active'); - activeTab.b.style.background = ''; - activeTab.b.style.borderColor = ''; - activeTab.b.style.color = ''; - } - - activeTab = tabs[id] || undefined; - - if(activeTab) { - activeTab.c.classList.add('fw-colour-picker-tab-container-active'); - activeTab.b.classList.add('fw-colour-picker-tab-button-active'); - activeTab.b.style.background = hexFormat(colour); - activeTab.b.style.borderColor = hexFormat(colour); - activeTab.b.style.color = hexFormat(textColour(colour)); - } - }; - - var createTab = function(id, name, construct) { - var tabContainer = construct(); - tabContainer.className = 'fw-colour-picker-tab-container fw-colour-picker-tab-' + id + '-container'; - tabbedContainer.appendChild(tabContainer); - - var tabButton = document.createElement('input'); - tabButton.type = 'button'; - tabButton.value = name; - tabButton.className = 'fw-colour-picker-tab-button fw-colour-picker-tab-' + id + '-button'; - tabButton.onclick = function() { switchTab(id); }; - tabbedList.appendChild(tabButton); - - tabs[id] = { c: tabContainer, b: tabButton }; - - if(activeTab === undefined) { - activeTab = tabs[id]; - tabContainer.className += ' fw-colour-picker-tab-container-active'; - tabButton.className += ' fw-colour-picker-tab-button-active'; - } - }; - - if(options.showPresetsTab) - createTab('presets', 'Presets', function() { - var presets = options.presets; - var cont = document.createElement('div'); - - for(var i = 0; i < presets.length; ++i) - (function(preset) { - var option = document.createElement('a'); - option.href = 'javascript:void(0);'; - option.className = 'fw-colour-picker-presets-option'; - option.style.background = hexFormat(preset.c); - option.title = preset.n; - option.onclick = function() { - setColour(preset.c); - }; - onColourChange.push(function(value) { - option.classList[(value === preset.c ? 'add' : 'remove')]('fw-colour-picker-presets-option-active'); - }); - cont.appendChild(option); - })(presets[i]); - - return cont; - }); - - if(options.showGridTab) - createTab('grid', 'Grid', function() { - var greys = [0xFFFFFF, 0xEBEBEB, 0xD6D6D6, 0xC2C2C2, 0xADADAD, 0x999999, 0x858585, 0x707070, 0x5C5C5C, 0x474747, 0x333333, 0]; - var colours = [0x00A1D8, 0x0061FE, 0x4D22B2, 0x982ABC, 0xB92D5D, 0xFF4015, 0xFF6A00, 0xFFAB01, 0xFDC700, 0xFEFB41, 0xD9EC37, 0x76BB40]; - var shades = [-.675, -.499, -.345, -.134, 0, .134, .345, .499, .675]; - - var cont = document.createElement('div'); - - for(var i = 0; i < greys.length; ++i) - (function(grey) { - var option = document.createElement('a'); - option.href = 'javascript:void(0);'; - option.className = 'fw-colour-picker-grid-option'; - option.style.background = hexFormat(grey); - option.onclick = function() { - setColour(grey); - }; - onColourChange.push(function(value) { - option.classList[(value === grey ? 'add' : 'remove')]('fw-colour-picker-grid-option-active'); - }); - cont.appendChild(option); - })(greys[i]); - - for(var i = 0; i < shades.length; ++i) - for(var j = 0; j < colours.length; ++j) - (function(colour) { - var option = document.createElement('a'); - option.href = 'javascript:void(0);'; - option.className = 'fw-colour-picker-grid-option'; - option.style.background = hexFormat(colour); - option.onclick = function() { - setColour(colour); - }; - onColourChange.push(function(value) { - option.classList[(value === colour ? 'add' : 'remove')]('fw-colour-picker-grid-option-active'); - }); - cont.appendChild(option); - })(shadeColour(colours[j], shades[i])); - - return cont; - }); - - if(options.showSlidersTab) - createTab('sliders', 'Sliders', function() { - var cont = document.createElement('div'); - - var addSlider = function(id, name, update, apply) { - var sCont = document.createElement('div'); - sCont.className = 'fw-colour-picker-slider fw-colour-picker-slider-' + id; - cont.appendChild(sCont); - - var sName = document.createElement('div'); - sName.className = 'fw-colour-picker-slider-name'; - sName.textContent = name; - sCont.appendChild(sName); - - var sValue = document.createElement('div'); - sValue.className = 'fw-colour-picker-slider-value'; - sCont.appendChild(sValue); - - var sValueSliderCont = document.createElement('div'); - sValueSliderCont.className = 'fw-colour-picker-slider-value-slider-container'; - sValue.appendChild(sValueSliderCont); - - var sGradient = document.createElement('div'); - sGradient.className = 'fw-colour-picker-slider-gradient'; - sValueSliderCont.appendChild(sGradient); - - var sValueSlider = document.createElement('input'); - sValueSlider.type = 'range'; - if(sValueSlider.type === 'range') { - sValueSlider.className = 'fw-colour-picker-slider-value-slider'; - sValueSlider.min = '0'; - sValueSlider.max = '255'; - sValueSlider.onchange = function() { - setColour(apply(colour, sValueSlider.value)); - }; - sValueSliderCont.appendChild(sValueSlider); - } else - sValueSlider = undefined; - - var sValueInputContainer = document.createElement('div'); - sValueInputContainer.className = 'fw-colour-picker-slider-value-input-container'; - sValue.appendChild(sValueInputContainer); - - var sValueInput = document.createElement('input'); - sValueInput.className = 'fw-colour-picker-slider-value-input'; - sValueInput.type = 'number'; - sValueInput.min = '0'; - sValueInput.max = '255'; - sValueInput.onchange = function() { - setColour(apply(colour, sValueInput.value)); - }; - sValueInputContainer.appendChild(sValueInput); - - sGradient.onmousedown = function(ev) { - if(ev.button === 0) - setColour(apply(colour, Math.floor(255 * (Math.max(0, Math.min(200, (ev.layerX - 5))) / 200)))); - }; - - onColourChange.push(function(colour) { - if(sValueSlider) - sValueSlider.value = update(colour); - sValueInput.value = update(colour); - - var gradient = 'linear-gradient(to right, ' + hexFormat(apply(colour, 0)) + ', ' + hexFormat(apply(colour, 0xFF)) + ')'; - sGradient.style.background = ''; - sGradient.style.background = gradient; - if(!sGradient.style.background) - sGradient.style.background = '-moz-' + gradient; - if(!sGradient.style.background) - sGradient.style.background = '-webkit-' + gradient; - }); - }; - - addSlider('red', 'Red', - function(value) { return (value >> 16) & 0xFF; }, - function(colour, value) { return (colour & 0xFFFF) | (Math.min(255, Math.max(0, value)) << 16); } - ); - addSlider('green', 'Green', - function(value) { return (value >> 8) & 0xFF; }, - function(colour, value) { return (colour & 0xFF00FF) | (Math.min(255, Math.max(0, value)) << 8); } - ); - addSlider('blue', 'Blue', - function(value) { return value & 0xFF; }, - function(colour, value) { return (colour & 0xFFFF00) | Math.min(255, Math.max(0, value)); } - ); - - return cont; - }); - - if(activeTab) { - height += 261; - form.appendChild(tabbed); - } - - var middleRow = document.createElement('div'); - middleRow.className = 'fw-colour-picker-middle-row'; - form.appendChild(middleRow); - - var colourPreviewContainer = document.createElement('div'); - colourPreviewContainer.className = 'fw-colour-picker-colour-preview-container'; - middleRow.appendChild(colourPreviewContainer); - - var colourPreview = document.createElement('div'); - colourPreview.className = 'fw-colour-picker-colour-preview'; - colourPreviewContainer.appendChild(colourPreview); - onColourChange.push(function(colour) { - colourPreview.style.background = hexFormat(colour); - }); - - var values = {}; - var valuesContainer = document.createElement('div'); - valuesContainer.className = 'fw-colour-picker-values-container'; - middleRow.appendChild(valuesContainer); - - var addValue = function(id, name, type, format, change) { - var valueContainer = document.createElement('label'); - valueContainer.className = 'fw-colour-picker-values-child fw-colour-picker-' + id + '-value'; - valuesContainer.appendChild(valueContainer); - - var valueLabel = document.createElement('div'); - valueLabel.textContent = name; - valueLabel.className = 'fw-colour-picker-values-child-label fw-colour-picker-' + id + '-value-label'; - valueContainer.appendChild(valueLabel); - - var valueInput = document.createElement('input'); - valueInput.type = type; - valueInput.value = '0'; - valueInput.className = 'fw-colour-picker-values-child-input fw-colour-picker-' + id + '-value-input'; - valueInput.onchange = function() { - change(valueInput.value); - }; - valueContainer.appendChild(valueInput); - - onColourChange.push(function(colour) { - valueInput.value = format(colour); - }); - - values[id] = { c: valueContainer, l: valueLabel, i: valueInput }; - }; - - if(options.showHexValue) - addValue('hex', 'Hex', 'text', function(value) { - return hexFormat(value); - }, function(value) { - while(value.substring(0, 1) === '#') - value = value.substring(1); - value = value.substring(0, 6); - - if(value.length === 3) - value = value.substring(0, 1) + value.substring(0, 1) - + value.substring(1, 2) + value.substring(1, 2) - + value.substring(2, 3) + value.substring(2, 3); - - if(value.length === 6) - setColour(parseInt(value, 16)); - }); - - if(options.showRawValue) - addValue('raw', 'Raw', 'number', function(value) { - return value; - }, function(value) { - setColour(Math.min(0xFFFFFF, Math.max(0, parseInt(value)))); - }); - - var buttons = {}; - var buttonsContainer = document.createElement('div'); - buttonsContainer.className = 'fw-colour-picker-buttons-container'; - form.appendChild(buttonsContainer); - - var buttonsContainerInner = document.createElement('div'); - buttonsContainerInner.className = 'fw-colour-picker-buttons-container-inner'; - buttonsContainer.appendChild(buttonsContainerInner); - - var addButton = function(id, name, action) { - var button = document.createElement('input'); - button.className = 'fw-colour-picker-buttons-button fw-colour-picker-buttons-' + id + '-button'; - if(action === null) { - button.className += ' fw-colour-picker-buttons-button-submit'; - onColourChange.push(function(colour, text) { - button.style.background = hexFormat(colour); - button.style.color = hexFormat(text); - }); - button.type = 'submit'; - } else { - button.onclick = function() { action(); }; - button.type = 'button'; - } - button.value = name; - buttonsContainerInner.appendChild(button); - buttons[id] = { b: button }; - }; - - addButton('cancel', 'Cancel', cancel); - addButton('apply', 'Apply', null); - - var setPosition = function(x, y) { - container.style.top = y >= 0 ? (y.toString() + 'px') : ''; - container.style.left = x >= 0 ? (x.toString() + 'px') : ''; - }; - - setPosition(options.posX, options.posY); - runOnColourChange(); - - var appendTo = function(parent) { - parent.appendChild(container); - }; - - var pub = { - getWidth: function() { return 290; }, - getHeight: function() { return height; }, - getColour: function() { return colour; }, - getContainer: function() { return container; }, - setColour: setColour, - appendTo: appendTo, - setPosition: setPosition, - switchTab: switchTab, - close: close, - suggestPosition: function(mouseEvent) { - var x = 10, y = 10; - - if(document.body.clientWidth > 340) { - x = mouseEvent.clientX; - y = mouseEvent.clientY; - - var height = pub.getHeight(), - width = pub.getWidth(); - - if(y > height + 20) - y -= height; - if(x > document.body.clientWidth - width - 20) - x -= width; - } - - return { - x: x, - y: y, - }; - }, - }; - - return pub; -}; -FwColourPicker.hexFormat = function(raw) { - var str = raw.toString(16).substring(0, 6); - if(str.length < 6) - str = '000000'.substring(str.length) + str; - return '#' + str; -}; diff --git a/public/picker.css b/src/mami.css/colpick.css similarity index 52% rename from public/picker.css rename to src/mami.css/colpick.css index 6b14151..8223512 100644 --- a/public/picker.css +++ b/src/mami.css/colpick.css @@ -1,12 +1,11 @@ -.fw-colour-picker { +.colpick { + accent-color: var(--colpick-colour, #000); border-radius: 5px; - border: 2px solid #123456; + border: 2px solid var(--colpick-colour, #000); padding: 3px; display: flex; position: absolute; box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; background-color: #444; color: #fff; box-shadow: 0 3px 10px #000; @@ -14,34 +13,30 @@ font-size: 12px; line-height: 20px; width: 290px; - transition: width .2s, border-color .2s; } -.fw-colour-picker-form { +.colpick-form { width: 100%; } -.fw-colour-picker-tabbed { +.colpick-tabbed { width: 100%; margin-bottom: 3px; } -.fw-colour-picker-tabbed-container { - border: 2px solid #123456; +.colpick-tabbed-container { + border: 2px solid var(--colpick-colour, #000); box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; border-radius: 5px 5px 0 0; height: 234px; overflow: auto; - transition: border-color .2s; } -.fw-colour-picker-tabbed-list { +.colpick-tabbed-list { background-color: #222; border-radius: 0 0 5px 5px; overflow: auto; } -.fw-colour-picker-tab-button { +.colpick-tab-button { background: #333; color: #fff; border-radius: 0; @@ -50,92 +45,86 @@ padding: 3px 5px; height: 24px; margin-right: 1px; - transition: background .2s, border-color .2s; box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; cursor: pointer; } -.fw-colour-picker-tab-button:hover { +.colpick-tab-button:hover { background: #444; border-color: #444; } -.fw-colour-picker-tab-button:focus { +.colpick-tab-button:focus { border-color: #fff; } -.fw-colour-picker-tab-button-active { - background: #123456; - border-color: #123456; - color: #123456; +.colpick-tab-button-active { + background: var(--colpick-colour, #000); + border-color: var(--colpick-colour, #000); + color: var(--colpick-text, #000); } -.fw-colour-picker-middle-row { +.colpick-middle-row { width: 100%; margin-bottom: 3px; height: 60px; } -.fw-colour-picker-colour-preview-container { +.colpick-colour-preview-container { display: inline-block; width: 60px; height: 60px; vertical-align: middle; } -.fw-colour-picker-colour-preview { +.colpick-colour-preview { display: block; width: 60px; height: 60px; border-radius: 5px; - background: #123456; + background: var(--colpick-colour, #000); } -.fw-colour-picker-values-container { +.colpick-values-container { display: inline-block; vertical-align: middle; } -.fw-colour-picker-values-child { +.colpick-values-child { display: block; padding: 2px 3px; margin: 1px; margin-left: 31px; cursor: text; } -.fw-colour-picker-values-child-label { +.colpick-values-child-label { font-weight: 700; width: 40px; display: inline-block; margin-right: 6px; text-align: right; } -.fw-colour-picker-values-child-input { +.colpick-values-child-input { display: inline-block; border: 1px solid #222; box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; background: #333; border-radius: 0; color: #fff; padding: 1px; width: 100px; - transition: border-color .2s; outline-style: none; } -.fw-colour-picker-values-child-input:focus { +.colpick-values-child-input:focus { border-color: #777; } -.fw-colour-picker-buttons-container { +.colpick-buttons-container { text-align: right; margin: 1px; } -.fw-colour-picker-buttons-container-inner { +.colpick-buttons-container-inner { text-align: left; display: inline-block; } -.fw-colour-picker-buttons-button { +.colpick-buttons-button { border-radius: 5px; background: #222; border-width: 0; @@ -146,116 +135,107 @@ margin-left: 5px; cursor: pointer; } -.fw-colour-picker-buttons-button:focus { +.colpick-buttons-button:focus { box-shadow: 0 0 0 1px #000, inset 0 0 0 1px #fff; } -.fw-colour-picker-buttons-button-submit { +.colpick-buttons-button-submit { font-weight: 700; - color: #123456; - background: #123456; - transition: background .2s; + color: var(--colpick-text, #fff); + background: var(--colpick-colour, #000); } -.fw-colour-picker-tab-container { - display: none; +.colpick-tab-container {} +.colpick-tab-container-inactive { + display: none !important; } -.fw-colour-picker-tab-container-active { + +.colpick-tab-presets-container { + padding: 2px; + display: grid; + grid-template-columns: repeat(6, minmax(0, 1fr)); + gap: 3px; +} +.colpick-presets-option { display: block; -} - -.fw-colour-picker-tab-presets-container { - text-align: center; - padding-top: 3px; - padding-left: 3px; -} -.fw-colour-picker-presets-option { - display: inline-block; - vertical-align: middle; width: 40px; height: 40px; - margin-right: 3px; - margin-bottom: 3px; border-radius: 5px; text-decoration: none; color: #fff; } -.fw-colour-picker-presets-option:focus { +.colpick-presets-option:focus { box-shadow: 0 0 0 1px #fff, 0 0 0 2px #000, inset 0 0 0 1px #000; } -.fw-colour-picker-presets-option-active { +.colpick-presets-option-active { box-shadow: 0 0 0 1px #000, inset 0 0 0 1px #fff; } -.fw-colour-picker-tab-grid-container { - text-align: center; +.colpick-tab-grid-container { + display: grid; + grid-template-columns: repeat(12, minmax(0, 1fr)); } -.fw-colour-picker-grid-option { - display: inline-block; - vertical-align: middle; +.colpick-grid-option { width: 23px; height: 23px; z-index: 1; - position: relative; cursor: cell; } -.fw-colour-picker-grid-option:focus { +.colpick-grid-option:focus { box-shadow: 0 0 0 1px #fff, 0 0 0 2px #000, inset 0 0 0 1px #000; z-index: 3; } -.fw-colour-picker-grid-option-active { +.colpick-grid-option-active { box-shadow: 0 0 0 1px #000, inset 0 0 0 1px #fff; z-index: 2; } -.fw-colour-picker-slider { +.colpick-slider { margin: 0 2px; } -.fw-colour-picker-slider-gradient { +.colpick-slider-gradient { width: 100%; height: 6px; } -.fw-colour-picker-slider-name { +.colpick-slider-name { font-weight: 700; margin: 0 2px; } -.fw-colour-picker-slider-value-slider-container { +.colpick-slider-value-slider-container { display: inline-block; width: 200px; margin: 4px; } -.fw-colour-picker-slider-value-slider { +.colpick-slider-value-slider { + accent-color: var(--colpick-slider-colour, var(--colpick-colour, #000)); width: 100%; margin: 0; } -.fw-colour-picker-slider-value-input-container { +.colpick-slider-value-input-container { display: inline-block; vertical-align: top; text-align: center; width: 64px; } -.fw-colour-picker-slider-value-input { +.colpick-slider-value-input { display: inline-block; border: 1px solid #222; box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; background: #333; border-radius: 0; color: #fff; padding: 1px; width: 50px; - transition: border-color .2s; outline-style: none; } -.fw-colour-picker-slider-value-input:focus { +.colpick-slider-value-input:focus { border-color: #777; } -.fw-colour-picker-slider-red .fw-colour-picker-slider-value-input:focus { +.colpick-slider-red .colpick-slider-value-input:focus { border-color: #f00; } -.fw-colour-picker-slider-green .fw-colour-picker-slider-value-input:focus { +.colpick-slider-green .colpick-slider-value-input:focus { border-color: #0f0; } -.fw-colour-picker-slider-blue .fw-colour-picker-slider-value-input:focus { +.colpick-slider-blue .colpick-slider-value-input:focus { border-color: #00f; } diff --git a/src/mami.css/main.css b/src/mami.css/main.css index d03ef63..95c31c1 100644 --- a/src/mami.css/main.css +++ b/src/mami.css/main.css @@ -1,6 +1,8 @@ @include __animations.css; @include _main.css; + @include views.css; + @include chat.css; @include domaintrans.css; @include eeprom.css; @@ -13,6 +15,9 @@ @include setting.css; @include sidebar.css; @include umi.css; + +@include colpick.css; + @include zz_ls_archaic.css; @include zz_ls_blue.css; @include zz_ls_dark.css; diff --git a/src/mami.html b/src/mami.html index 32b908e..43d571c 100644 --- a/src/mami.html +++ b/src/mami.html @@ -8,7 +8,6 @@ - - diff --git a/src/mami.js/audio/context.js b/src/mami.js/audio/context.js index 95d7037..33228dd 100644 --- a/src/mami.js/audio/context.js +++ b/src/mami.js/audio/context.js @@ -1,58 +1,13 @@ +#include srle.js #include utility.js #include audio/buffer.js #include audio/source.js -const MamiSRLEEncode = function(input, cutoff) { - let output = '', last = '', repeat = 0; - - input = (input || '').toString(); - cutoff = cutoff || 1 - - for(let i = 0; i <= input.length; ++i) { - const chr = input[i]; - if(last === chr) - ++repeat; - else { - if(repeat > cutoff) - for(const repChr in repeat.toString()) output += ')!@#$%^&*('[parseInt(repChr)]; - else - output += last.repeat(repeat); - repeat = 0; - if(chr !== undefined) { - output += chr; - last = chr; - } - } - } - - return output; -}; - -const MamiSRLEDecode = function(input) { - let output = '', repeat = '', chr; - - input = (input || '').toString().split('').reverse(); - - for(;;) { - const chr = input.pop(), num = ')!@#$%^&*('.indexOf(chr); - if(num >= 0) repeat += num; - else { - if(repeat) { - output += output.slice(-1).repeat(parseInt(repeat)); - repeat = ''; - } - if(chr === undefined) break; - output += chr; - } - } - - return output; -}; const MamiDetectAutoPlaySource = '/+NIxA!!FhpbmcA#PA$wA@fgAV$#q$#/$#A#OUxBTUUzLjEwMAIeA!)UCCQC8CIA@gA@H49wpKWgA!%&/+MYxA$NIA$ExBTUUzLjEwMFV^%/+MYxDsA@NIA$FV&&/+MYxHYA@NIA$FV&&'; const MamiDetectAutoPlay = async () => { try { - const audio = $e('audio', { src: 'data:audio/mpeg;base64,' + MamiSRLEDecode(MamiDetectAutoPlaySource) }); + const audio = $e('audio', { src: 'data:audio/mpeg;base64,' + MamiSRLE.decode(MamiDetectAutoPlaySource) }); try { await audio.play(); diff --git a/src/mami.js/colpick/picker.jsx b/src/mami.js/colpick/picker.jsx new file mode 100644 index 0000000..a3730d5 --- /dev/null +++ b/src/mami.js/colpick/picker.jsx @@ -0,0 +1,374 @@ +const MamiColourPicker = function(callback, options, colour, onClose) { + if(typeof callback !== 'function') + return; + if(typeof options !== 'object') + options = {}; + if(typeof colour !== 'number') + colour = parseInt(colour || 0); + + const readThres = 168, + lumiRed = .299, + lumiGreen = .587, + lumiBlue = .114; + + const hexFormat = raw => { + let str = raw.toString(16).substring(0, 6); + if(str.length < 6) + str = '000000'.substring(str.length) + str; + return `#${str}`; + }; + + const extractRGB = raw => [ + (raw >> 16) & 0xFF, + (raw >> 8) & 0xFF, + raw & 0xFF, + ]; + + const calcLumi = raw => { + const rgb = extractRGB(raw); + return rgb[0] * lumiRed + + rgb[1] * lumiGreen + + rgb[2] * lumiBlue; + }; + + const textColour = raw => calcLumi(raw) > readThres ? 0 : 0xFFFFFF; + + const weightNum = (n1, n2, w) => { + w = Math.min(1, Math.max(0, w)); + return Math.round((n1 * w) + (n2 * (1 - w))); + }; + + const weightColour = (c1, c2, w) => { + c1 = extractRGB(c1); + c2 = extractRGB(c2); + return (weightNum(c1[0], c2[0], w) << 16) + | (weightNum(c1[1], c2[1], w) << 8) + | weightNum(c1[2], c2[2], w); + }; + + const shadeColour = (raw, offset) => { + if(offset == 0) + return raw; + + let dir = 0xFFFFFF; + if(offset < 0) { + dir = 0; + offset *= -1; + } + + return weightColour(dir, raw, offset); + }; + + const verifyOption = (name, type, def) => { + if(typeof options[name] !== type) + options[name] = def; + }; + + verifyOption('posX', 'number', -1); + verifyOption('posY', 'number', -1); + verifyOption('presets', 'object', []); + verifyOption('showPresetsTab', 'boolean', options.presets.length > 0); + verifyOption('showGridTab', 'boolean', true); + verifyOption('showSlidersTab', 'boolean', true); + verifyOption('showHexValue', 'boolean', true); + verifyOption('showRawValue', 'boolean', true); + verifyOption('autoClose', 'boolean', true); + + const onColourChange = []; + const runOnColourChange = () => { + const text = textColour(colour); + for(const handler of onColourChange) + handler(colour, text); + }; + + const setColour = raw => { + colour = parseInt(raw || 0) & 0xFFFFFF; + runOnColourChange(); + }; + + const runCallback = apply => { + const result = Object.defineProperties({}, { + apply: { value: apply }, + colour: { value: colour }, + hex: { get() { return hexFormat(colour); } }, + }); + + callback(result); + }; + + const apply = () => { + runCallback(true); + if(options.autoClose) + close(); + }; + + const cancel = () => { + runCallback(false); + if(options.autoClose) + close(); + }; + + const close = () => { + if(onClose && onClose()) + return; + container.parentNode.removeChild(container); + }; + + let height = 96; + + const container =
; + onColourChange.push((colour, text) => { + container.style.setProperty('--colpick-colour', hexFormat(colour)); + container.style.setProperty('--colpick-text', hexFormat(text)); + }); + + const form =
{ + ev.preventDefault(); + apply(); + return false; + }} />; + container.appendChild(form); + + const tabs = {}; + let activeTab = undefined; + + let tabbedContainer, tabbedList; + const tabbed =
+ {tabbedContainer =
} + {tabbedList =
} +
; + + const switchTab = (id) => { + if(activeTab == tabs[id]) + return; + + if(activeTab) { + activeTab.c.classList.toggle('colpick-tab-container-inactive', true); + activeTab.b.classList.toggle('colpick-tab-button-active', false); + } + + activeTab = tabs[id] || undefined; + + if(activeTab) { + activeTab.c.classList.toggle('colpick-tab-container-inactive', false); + activeTab.b.classList.toggle('colpick-tab-button-active', true); + } + }; + + const createTab = (id, name, construct) => { + const tabContainer = construct(); + tabContainer.className = `colpick-tab-container colpick-tab-${id}-container colpick-tab-container-inactive`; + tabbedContainer.appendChild(tabContainer); + + const tabButton = switchTab(id)}/>; + tabbedList.appendChild(tabButton); + + tabs[id] = { c: tabContainer, b: tabButton }; + + if(activeTab === undefined) { + activeTab = tabs[id]; + tabContainer.classList.remove('colpick-tab-container-inactive'); + tabButton.classList.add('colpick-tab-button-active'); + } + }; + + if(options.showPresetsTab) + createTab('presets', 'Presets', () => { + const presets = options.presets; + const cont =
; + + for(const preset of presets) { + const option = setColour(preset.c)}/>; + onColourChange.push(value => option.classList.toggle('colpick-presets-option-active', value === preset.c)); + cont.appendChild(option); + } + + return cont; + }); + + if(options.showGridTab) + createTab('grid', 'Grid', () => { + const greys = [0xFFFFFF, 0xEBEBEB, 0xD6D6D6, 0xC2C2C2, 0xADADAD, 0x999999, 0x858585, 0x707070, 0x5C5C5C, 0x474747, 0x333333, 0]; + const colours = [0x00A1D8, 0x0061FE, 0x4D22B2, 0x982ABC, 0xB92D5D, 0xFF4015, 0xFF6A00, 0xFFAB01, 0xFDC700, 0xFEFB41, 0xD9EC37, 0x76BB40]; + const shades = [-.675, -.499, -.345, -.134, 0, .134, .345, .499, .675]; + + const cont =
; + + for(const grey of greys) { + const option = setColour(grey)}/>; + onColourChange.push(value => option.classList.toggle('colpick-grid-option-active', value === grey)); + cont.appendChild(option); + } + + for(const shade of shades) + for(const colour of colours) { + const shaded = shadeColour(colour, shade); + const option = setColour(shaded)}/>; + onColourChange.push(value => option.classList.toggle('colpick-grid-option-active', value === shaded)); + cont.appendChild(option); + } + + return cont; + }); + + if(options.showSlidersTab) + createTab('sliders', 'Sliders', () => { + const cont =
; + + const addSlider = (id, name, update, apply) => { + let sGradient, sValueSlider, sValueInput; + + const sCont =
+
{name}
+
+
+ {sGradient =
{ if(ev.button === 0) setColour(apply(colour, Math.floor(255 * (Math.max(0, Math.min(200, (ev.layerX - 5))) / 200)))) }}/>} + {sValueSlider = setColour(apply(colour, sValueSlider.value))}/>} +
+
+ {sValueInput = setColour(apply(colour, sValueInput.value))}/>} +
+
+
; + cont.appendChild(sCont); + + onColourChange.push(colour => { + sCont.style.setProperty('--colpick-slider-colour', hexFormat(apply(0, update(colour)))); + sValueSlider.value = update(colour); + sValueInput.value = update(colour); + sGradient.style.background = `linear-gradient(to right, ${hexFormat(apply(colour, 0))}, ${hexFormat(apply(colour, 0xFF))})`; + }); + }; + + addSlider('red', 'Red', + value => (value >> 16) & 0xFF, + (colour, value) => (colour & 0xFFFF) | (Math.min(255, Math.max(0, value)) << 16) + ); + addSlider('green', 'Green', + value => (value >> 8) & 0xFF, + (colour, value) => (colour & 0xFF00FF) | (Math.min(255, Math.max(0, value)) << 8) + ); + addSlider('blue', 'Blue', + value => value & 0xFF, + (colour, value) => (colour & 0xFFFF00) | Math.min(255, Math.max(0, value)) + ); + + return cont; + }); + + if(activeTab) { + height += 261; + form.appendChild(tabbed); + } + + const values = {}; + let valuesContainer; + const middleRow =
+
+
+
+ {valuesContainer =
} +
; + form.appendChild(middleRow); + + const addValue = (id, name, type, format, change) => { + let valueLabel, valueInput; + const valueContainer = ; + valuesContainer.appendChild(valueContainer); + + onColourChange.push(colour => valueInput.value = format(colour)); + + values[id] = { c: valueContainer, l: valueLabel, i: valueInput }; + }; + + if(options.showHexValue) + addValue('hex', 'Hex', 'text', value => hexFormat(value), value => { + while(value.substring(0, 1) === '#') + value = value.substring(1); + value = value.substring(0, 6); + + if(value.length === 3) + value = value.substring(0, 1) + value.substring(0, 1) + + value.substring(1, 2) + value.substring(1, 2) + + value.substring(2, 3) + value.substring(2, 3); + + if(value.length === 6) + setColour(parseInt(value, 16)); + }); + + if(options.showRawValue) + addValue('raw', 'Raw', 'number', value => value, value => setColour(Math.min(0xFFFFFF, Math.max(0, parseInt(value))))); + + let buttonsContainerInner; + const buttons = {}; + const buttonsContainer =
+ {buttonsContainerInner =
} +
; + form.appendChild(buttonsContainer); + + const addButton = (id, name, action) => { + const button = ; + + if(action === null) { + button.classList.add('colpick-buttons-button-submit'); + button.type = 'submit'; + } else { + button.onclick = () => action(); + button.type = 'button'; + } + + buttonsContainerInner.appendChild(button); + buttons[id] = { b: button }; + }; + + addButton('cancel', 'Cancel', cancel); + addButton('apply', 'Apply', null); + + const setPosition = (x, y) => { + container.style.top = y >= 0 ? `${y}px` : ''; + container.style.left = x >= 0 ? `${x}px` : ''; + }; + + setPosition(options.posX, options.posY); + runOnColourChange(); + + const appendTo = parent => parent.appendChild(container); + + const pub = { + getWidth: () => 290, + getHeight: () => height, + getColour: () => colour, + getContainer: () => container, + setColour: setColour, + appendTo: appendTo, + setPosition: setPosition, + switchTab: switchTab, + close: close, + suggestPosition: mouseEvent => { + let x = 10, y = 10; + + if(document.body.clientWidth > 340) { + x = mouseEvent.clientX; + y = mouseEvent.clientY; + + let height = pub.getHeight(), + width = pub.getWidth(); + + if(y > height + 20) + y -= height; + if(x > document.body.clientWidth - width - 20) + x -= width; + } + + return { + x: x, + y: y, + }; + }, + }; + + return pub; +}; diff --git a/src/mami.js/srle.js b/src/mami.js/srle.js new file mode 100644 index 0000000..00da67d --- /dev/null +++ b/src/mami.js/srle.js @@ -0,0 +1,63 @@ +const MamiSRLE = (() => { + return { + encode: (input, cutoff) => { + let output = '', + last = '', + repeat = 0; + + input = (input || '').toString(); + cutoff = cutoff || 1 + + for(let i = 0; i <= input.length; ++i) { + const chr = input[i]; + + if(last === chr) + ++repeat; + else { + if(repeat > cutoff) + for(const repChr in repeat.toString()) + output += ')!@#$%^&*('[parseInt(repChr)]; + else + output += last.repeat(repeat); + + repeat = 0; + + if(chr !== undefined) { + output += chr; + last = chr; + } + } + } + + return output; + }, + + decode: input => { + let output = '', + repeat = '', + chr; + + input = (input || '').toString().split('').reverse(); + + for(;;) { + const chr = input.pop(), num = ')!@#$%^&*('.indexOf(chr); + + if(num >= 0) + repeat += num; + else { + if(repeat) { + output += output.slice(-1).repeat(parseInt(repeat)); + repeat = ''; + } + + if(chr === undefined) + break; + + output += chr; + } + } + + return output; + }, + }; +})(); diff --git a/src/mami.js/ui/markup.js b/src/mami.js/ui/markup.js index 3505f3f..19dbb42 100644 --- a/src/mami.js/ui/markup.js +++ b/src/mami.js/ui/markup.js @@ -1,5 +1,6 @@ #include common.js #include utility.js +#include colpick/picker.jsx #include ui/elems.js #include ui/input-menus.js #include ui/markup.js @@ -21,13 +22,10 @@ Umi.UI.Markup = (function() { const elem = this; elem.dataset.umiPickerVisible = 'yes'; - const picker = new FwColourPicker( - function(picker, result) { - if(result !== null) - insertRaw( - '[color=' + FwColourPicker.hexFormat(result) + ']', - '[/color]' - ); + const picker = new MamiColourPicker( + function(result) { + if(result.apply) + insertRaw(`[color=${result.hex}]`, '[/color]'); }, { presets: futami.get('colours') }, null, function() { elem.dataset.umiPickerVisible = 'no'; }