198 lines
6.6 KiB
JavaScript
198 lines
6.6 KiB
JavaScript
#include args.js
|
|
#include colour.js
|
|
#include utility.js
|
|
#include controls/tabs.js
|
|
#include colpick/tgrid.jsx
|
|
#include colpick/tpresets.jsx
|
|
#include colpick/tsliders.jsx
|
|
#include colpick/vhex.jsx
|
|
#include colpick/vraw.jsx
|
|
|
|
const MamiColourPicker = function(options) {
|
|
options = MamiArgs('options', options, define => {
|
|
define('colour').default(0).filter(value => Math.min(0xFFFFFF, Math.max(0, value))).done();
|
|
define('posX').default(-1).done();
|
|
define('posY').default(-1).done();
|
|
define('presets').default([]).constraint(value => Array.isArray(value)).done();
|
|
define('showPresetsTab').default(true).done();
|
|
define('showGridTab').default(true).done();
|
|
define('showSlidersTab').default(true).done();
|
|
define('showHexValue').default(true).done();
|
|
define('showRawValue').default(true).done();
|
|
define('showDialogButtons').default(true).done();
|
|
});
|
|
|
|
let colour;
|
|
const needsColour = [];
|
|
|
|
let promiseResolve;
|
|
const runResolve = () => {
|
|
if(promiseResolve !== undefined)
|
|
promiseResolve(colour);
|
|
close();
|
|
};
|
|
|
|
let promiseReject;
|
|
const runReject = () => {
|
|
if(promiseReject !== undefined)
|
|
promiseReject();
|
|
close();
|
|
};
|
|
|
|
let tabsElem, tabsContainer, tabsList;
|
|
let values, buttons;
|
|
|
|
const html = <form class="colpick" style={{ zIndex: '9001' }} onsubmit={ev => { ev.preventDefault(); runResolve(); return false; }}>
|
|
{tabsElem = <div class="colpick-tabbed">
|
|
{tabsContainer = <div class="colpick-tabbed-container"/>}
|
|
{tabsList = <div class="colpick-tabbed-list"/>}
|
|
</div>}
|
|
<div class="colpick-middle-row">
|
|
<div class="colpick-colour-preview-container">
|
|
<div class="colpick-colour-preview"/>
|
|
</div>
|
|
{values = <div class="colpick-values-container"/>}
|
|
</div>
|
|
<div class="colpick-buttons-container">
|
|
{buttons = <div class="colpick-buttons-container-inner"/>}
|
|
</div>
|
|
</form>;
|
|
|
|
const close = () => html.parentNode.removeChild(html);
|
|
|
|
const setColour = (raw, mask) => {
|
|
raw = typeof raw === 'number' ? (parseInt(raw) & 0xFFFFFF) : 0;
|
|
mask = typeof mask === 'number' ? parseInt(mask) : ~0;
|
|
|
|
colour = (colour & ~mask) | (raw & mask);
|
|
|
|
const text = MamiColour.text(colour);
|
|
html.style.setProperty('--colpick-colour', MamiColour.hex(colour));
|
|
html.style.setProperty('--colpick-text', MamiColour.hex(text));
|
|
|
|
for(const info of needsColour)
|
|
if('updateColour' in info)
|
|
info.updateColour(colour, text);
|
|
};
|
|
|
|
const setPosition = pos => {
|
|
if(typeof pos !== 'object')
|
|
throw 'pos must be an object';
|
|
|
|
html.style.top = 'y' in pos && pos.y >= 0 ? `${pos.y}px` : null;
|
|
html.style.left = 'x' in pos && pos.x >= 0 ? `${pos.x}px` : '';
|
|
};
|
|
|
|
const tabs = new MamiTabsControl({
|
|
onAdd: ctx => {
|
|
const name = ctx.info.getName(),
|
|
containerName = `colpick-tab-${name}-container`,
|
|
buttonName = `colpick-tab-${name}-button`;
|
|
|
|
needsColour.push(ctx.info);
|
|
ctx.info.onChange(setColour);
|
|
|
|
ctx.elem.className = `colpick-tab-container ${containerName} colpick-tab-container-inactive`;
|
|
tabsContainer.appendChild(ctx.elem);
|
|
|
|
tabsList.appendChild(<input type="button" value={ctx.title}
|
|
class={['colpick-tab-button', buttonName]}
|
|
onclick={ctx.onClick}/>);
|
|
},
|
|
onRemove: ctx => {
|
|
const name = ctx.info.getName();
|
|
$rq(`.colpick-tab-${name}-button`);
|
|
$rq(`.colpick-tab-${name}-container`);
|
|
},
|
|
onSwitch: ctx => {
|
|
if(ctx.from !== undefined) {
|
|
ctx.from.elem.classList.toggle('colpick-tab-container-inactive', true);
|
|
$q(`.colpick-tab-${ctx.from.info.getName()}-button`).classList.toggle('colpick-tab-button-active', false);
|
|
}
|
|
|
|
ctx.elem.classList.toggle('colpick-tab-container-inactive', false);
|
|
$q(`.colpick-tab-${ctx.info.getName()}-button`).classList.toggle('colpick-tab-button-active', true);
|
|
},
|
|
});
|
|
|
|
if(options.showPresetsTab && options.presets.length > 0)
|
|
tabs.add(new MamiColourPickerPresetsTab(options.presets));
|
|
if(options.showGridTab)
|
|
tabs.add(new MamiColourPickerGridTab);
|
|
if(options.showSlidersTab)
|
|
tabs.add(new MamiColourPickerSlidersTab);
|
|
|
|
if(tabs.count() < 1)
|
|
html.removeChild(tabsElem);
|
|
|
|
const addValue = (id, name, valueInfo) => {
|
|
needsColour.push(valueInfo);
|
|
valueInfo.onChange(setColour);
|
|
values.appendChild(<label class={['colpick-values-child', `colpick-${id}-value`]}>
|
|
<div class={['colpick-values-child-label', `colpick-${id}-value-label`]}>{name}</div>
|
|
{valueInfo}
|
|
</label>);
|
|
};
|
|
|
|
if(options.showHexValue)
|
|
addValue('hex', 'Hex', new MamiColourPickerValueHex);
|
|
if(options.showRawValue)
|
|
addValue('raw', 'Raw', new MamiColourPickerValueRaw);
|
|
|
|
const addButton = (id, name, action) => {
|
|
const button = <input class={['colpick-buttons-button', `colpick-buttons-${id}-button`]} value={name}/>;
|
|
|
|
if(action === undefined) {
|
|
button.classList.add('colpick-buttons-button-submit');
|
|
button.type = 'submit';
|
|
} else {
|
|
button.onclick = () => action();
|
|
button.type = 'button';
|
|
}
|
|
|
|
buttons.appendChild(button);
|
|
};
|
|
|
|
if(options.showDialogButtons) {
|
|
addButton('cancel', 'Cancel', runReject);
|
|
addButton('apply', 'Apply');
|
|
}
|
|
|
|
setPosition({ x: options.posX, y: options.posY });
|
|
setColour(options.colour);
|
|
|
|
return {
|
|
getElement: () => html,
|
|
getColour: () => colour,
|
|
setColour: setColour,
|
|
setPosition: setPosition,
|
|
close: close,
|
|
dialog: pos => {
|
|
if(pos !== undefined)
|
|
setPosition(pos);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
promiseResolve = resolve;
|
|
promiseReject = reject;
|
|
});
|
|
},
|
|
suggestPosition: mouseEvent => {
|
|
let x = 10, y = 10;
|
|
|
|
if(html.parentNode.clientWidth > 340) {
|
|
x = mouseEvent.clientX;
|
|
y = mouseEvent.clientY;
|
|
|
|
const bb = html.getBoundingClientRect();
|
|
|
|
if(y > bb.height + 20)
|
|
y -= bb.height;
|
|
if(x > html.parentNode.clientWidth - bb.width - 20)
|
|
x -= bb.width;
|
|
}
|
|
|
|
return { x: x, y: y };
|
|
},
|
|
};
|
|
};
|