first commit
This commit is contained in:
+770
@@ -0,0 +1,770 @@
|
||||
import { Ut } from '../utils/Ut';
|
||||
import { Boot } from './Boot';
|
||||
import { $, El, EvtOptions } from '../utils/dom';
|
||||
import { Render } from './Render';
|
||||
/*
|
||||
* Loader Class
|
||||
*/
|
||||
export class App extends Boot {
|
||||
|
||||
// App Loaded state
|
||||
static #started = false;
|
||||
|
||||
// App registry
|
||||
static registry = {};
|
||||
|
||||
/**
|
||||
* App Class Register
|
||||
*/
|
||||
static register(...classRefList) {
|
||||
|
||||
if (App.#started) {
|
||||
App.log('Register already called!');
|
||||
return;
|
||||
}
|
||||
|
||||
App.#started = true;
|
||||
|
||||
classRefList.forEach( classRef => App.registry[ classRef.name ] = classRef);
|
||||
|
||||
if (App.registry.Main) {
|
||||
Boot.ready(_ => new App.registry.Main);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set User Role
|
||||
*/
|
||||
static setRole(role) {
|
||||
App.role = role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Main Title
|
||||
*/
|
||||
static updateMainTitle(title) {
|
||||
$('.top-toolbar h1')?.dxHtml(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Card Title Wrapper
|
||||
*/
|
||||
static cardTitleWrapper(card) {
|
||||
|
||||
let content = card.dxFind('.content-card') || card;
|
||||
let topBar = content.dxFind('.top-bar');
|
||||
|
||||
if (!topBar) {
|
||||
topBar = El('div', { class: 'top-bar' });
|
||||
content.prepend(topBar);
|
||||
}
|
||||
|
||||
let topBarInner = topBar.dxFind('.top-bar-inner');
|
||||
|
||||
if (!topBarInner) {
|
||||
topBarInner = topBar.appendChild( El('div', { class: 'top-bar-inner' }) );
|
||||
}
|
||||
|
||||
let titleWrapper = topBarInner.dxFind('.title-wrapper');
|
||||
|
||||
if (!titleWrapper) {
|
||||
titleWrapper = topBarInner.appendChild(El('div', { class: 'title-wrapper' }));
|
||||
}
|
||||
|
||||
return titleWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Card Title
|
||||
*/
|
||||
static updateCardTitle(cardName, title) {
|
||||
|
||||
let card = App.viewEl.dxFind('.card-'+ cardName);
|
||||
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
let elTitle = card.dxFind('h2.title');
|
||||
|
||||
if (elTitle) {
|
||||
elTitle.dxHtml(title).classList.remove('hide');
|
||||
return;
|
||||
}
|
||||
|
||||
elTitle = El('h2', { class: 'title' });
|
||||
|
||||
if (Ut.isStr(title)) {
|
||||
elTitle.dxHtml(title);
|
||||
}
|
||||
else {
|
||||
elTitle.append(title);
|
||||
}
|
||||
|
||||
App.cardTitleWrapper(card).prepend(elTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Card Description
|
||||
*/
|
||||
static updateCardDescr(cardName, descr) {
|
||||
|
||||
let card = App.viewEl.dxFind('.card-'+ cardName);
|
||||
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
let elDescr = card.dxFind('p.descr');
|
||||
|
||||
if (elDescr) {
|
||||
elDescr.dxHtml(descr).classList.remove('hide');
|
||||
return;
|
||||
}
|
||||
|
||||
elDescr = El('p', { class: 'descr' });
|
||||
|
||||
if (Ut.isStr(title)) {
|
||||
elTitle.dxHtml(title);
|
||||
}
|
||||
else {
|
||||
elTitle.append(title);
|
||||
}
|
||||
|
||||
App.getCardTitleWrapper(card).append(elDescr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append Card Toolbar
|
||||
*/
|
||||
static addCardToolbar(cardName, data) {
|
||||
|
||||
let card = App.viewEl.dxFind('.card-'+ cardName);
|
||||
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
let toolbar = card.dxFind('.top-bar-inner');
|
||||
|
||||
if (Ut.isStr(data)) {
|
||||
toolbar?.insertAdjacentHTML('beforeend', data);
|
||||
}
|
||||
else {
|
||||
toolbar?.append(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Card Content
|
||||
*/
|
||||
static updateCardContent(cardName, data) {
|
||||
|
||||
let card = App.viewEl.dxFind('.card-'+ cardName);
|
||||
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
let container = card.dxFind('.container');
|
||||
|
||||
if (Ut.isStr(data)) {
|
||||
container?.dxHtml(data);
|
||||
}
|
||||
else {
|
||||
container?.dxHtml('').append(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append Card Content
|
||||
*/
|
||||
static addCardContent(cardName, data) {
|
||||
|
||||
let card = App.viewEl.dxFind('.card-'+ cardName);
|
||||
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
let container = card.dxFind('.container');
|
||||
|
||||
if (Ut.isStr(data)) {
|
||||
container?.insertAdjacentHTML('beforeend', data);
|
||||
}
|
||||
else {
|
||||
container?.append(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Label Info
|
||||
*/
|
||||
static updateLabel(name, val, isHtml) {
|
||||
|
||||
let label = App.viewEl.dxFind('.field-info[data-name="'+ name +'"]');
|
||||
|
||||
if (!label) {
|
||||
return;
|
||||
}
|
||||
|
||||
label.classList.toggle('hide', !val);
|
||||
|
||||
if (isHtml) {
|
||||
label.dxFind('.label-value')?.dxHtml(val);
|
||||
}
|
||||
else {
|
||||
label.dxFind('.label-value')?.dxText(val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render UI Component
|
||||
*
|
||||
* @param string id Component ID
|
||||
* @param object template Template Object Vars
|
||||
*
|
||||
*/
|
||||
static render(id, template) {
|
||||
|
||||
let token = id.split('.');
|
||||
|
||||
if (token.length != 2) {
|
||||
App.log('Invalid component ID!');
|
||||
return null;
|
||||
}
|
||||
|
||||
let nodeObj = null;
|
||||
|
||||
if (App._section) {
|
||||
|
||||
let mainNode = App.intData?.section[App._section[0]];
|
||||
nodeObj = mainNode?.children?.[token[0]]?.[token[1]];
|
||||
}
|
||||
else {
|
||||
nodeObj = App.intData?.[token[0]]?.[token[1]];
|
||||
}
|
||||
|
||||
if (!nodeObj) {
|
||||
App.log('This component ID doesn\'t exist!');
|
||||
return null;
|
||||
}
|
||||
|
||||
nodeObj._type = token[0];
|
||||
nodeObj.name = token[1];
|
||||
nodeObj.template = template || {};
|
||||
|
||||
return Render.makeElement(nodeObj, null, { vars: App.vars || {} });
|
||||
}
|
||||
|
||||
/**
|
||||
* Mount View
|
||||
*/
|
||||
static mountViewEl(viewEl) {
|
||||
|
||||
if (!viewEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewEl.classList.contains('sp-card')) {
|
||||
App.toolbarEl = viewEl.dxFind('.top-bar-inner');
|
||||
App.tabMenuEl = viewEl.dxFind('.tab-menu');
|
||||
App.viewEl = viewEl.dxFind('.container');
|
||||
}
|
||||
else {
|
||||
App.viewEl = viewEl;
|
||||
}
|
||||
|
||||
App.contentEl.replaceChildren(viewEl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Root Main
|
||||
*/
|
||||
static mountView( component ) {
|
||||
App.mountViewEl(App.render(component));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call Module Class
|
||||
*/
|
||||
static callModClass(section, id) {
|
||||
|
||||
if (section.length == 1) {
|
||||
|
||||
const regModule = App.registry[ id.charAt(0).toUpperCase() + id.slice(1) ];
|
||||
|
||||
App.instance = regModule ? new regModule() : null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
id = id.split('.')[0];
|
||||
|
||||
const regModule = App.registry[ id.charAt(0).toUpperCase() + id.slice(1) ];
|
||||
|
||||
if (regModule) {
|
||||
|
||||
console.log( section )
|
||||
|
||||
App.instance = new regModule;
|
||||
App.instance[ section[1] ] ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init Module
|
||||
*/
|
||||
static initModule(id, vars, opts) {
|
||||
|
||||
vars = vars || {};
|
||||
|
||||
if (opts === 1 || opts === true) {
|
||||
opts = { back: 1 };
|
||||
}
|
||||
else {
|
||||
opts = opts || { back: 0 };
|
||||
}
|
||||
|
||||
if (opts.back === true) {
|
||||
opts.back = 1;
|
||||
}
|
||||
|
||||
App._section = id.split('.');
|
||||
|
||||
let rootNode = App.intData.section[ App._section[0] ];
|
||||
|
||||
// RootNode is missing .. Just call module class
|
||||
if (!Ut.isSet(rootNode)) {
|
||||
App.callModClass(App._section, id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Call destructor if it's present
|
||||
if (App.instance && Ut.isFn(App.instance.destructor)) {
|
||||
App.instance.destructor(App.section);
|
||||
}
|
||||
|
||||
// Destroy old global events
|
||||
App.destroyOldGlobalEvents();
|
||||
|
||||
// Set main section title
|
||||
let title = rootNode.title || '';
|
||||
|
||||
// Subsection present
|
||||
if (App._section.length == 2) {
|
||||
|
||||
rootNode = Object.assign({}, rootNode, { that: rootNode.children.section[App._section[1]] });
|
||||
|
||||
// Set subsection title
|
||||
if (rootNode.that.title) {
|
||||
title = rootNode.that.title;
|
||||
}
|
||||
}
|
||||
|
||||
// Set section root (rootnode children)
|
||||
App.r = rootNode.children || {};
|
||||
|
||||
// Set Stack
|
||||
|
||||
if (!opts.back) {
|
||||
App.stack = null;
|
||||
}
|
||||
else if (!App.stack) {
|
||||
App.stack = { id: App.section, vars: App.vars, back: App.back };
|
||||
}
|
||||
|
||||
// This is the current section
|
||||
App.section = id;
|
||||
|
||||
// Section Main (null at this point)
|
||||
App.viewEl = null;
|
||||
|
||||
// Set section vars
|
||||
App.vars = vars || {};
|
||||
|
||||
// Set section back data
|
||||
App.back = opts.back;
|
||||
|
||||
// Set ref shortcut
|
||||
|
||||
App.ref = {};
|
||||
|
||||
if (opts.reference) {
|
||||
|
||||
for (let name of opts.reference) {
|
||||
let section = App.intData.section[ name ];
|
||||
App.ref[ name ] = section;
|
||||
}
|
||||
}
|
||||
|
||||
// Set listener evt options
|
||||
EvtOptions.nsEvent = true;
|
||||
EvtOptions.section = id;
|
||||
|
||||
// Call module class at this point
|
||||
App.callModClass(App._section, id);
|
||||
|
||||
// Fix After Calling
|
||||
|
||||
if (App.viewEl) {
|
||||
|
||||
if (title) {
|
||||
App.updateMainTitle(title);
|
||||
}
|
||||
|
||||
if (App.menuFlag) {
|
||||
App.switchLeftMenu(App._section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy Old Global Events
|
||||
*/
|
||||
static destroyOldGlobalEvents() {
|
||||
|
||||
if (App.section) {
|
||||
window.dxOff(`${App.section}*`);
|
||||
document.dxOff(`${App.section}*`);
|
||||
document.body.dxOff(`${App.section}*`);
|
||||
}
|
||||
|
||||
// Destroy all TinyMce Instances
|
||||
if (Ut.isSet(window.tinymce) && tinymce.editors) {
|
||||
for (let i = tinymce.editors.length - 1; i > -1; i--) {
|
||||
tinymce.get(tinymce.editors[i].id).destroy();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch Left menu
|
||||
*/
|
||||
static switchLeftMenu = function(rid) {
|
||||
|
||||
let menuItem = App.leftMenuItems.dxFind('li[data-init="'+ rid.join('.') +'"]');
|
||||
|
||||
$('.left-menu li.active')?.classList.remove('active');
|
||||
$('.left-menu li.active')?.classList.remove('active');
|
||||
|
||||
if (menuItem) {
|
||||
|
||||
menuItem?.classList.add('active');
|
||||
|
||||
if (rid.length == 2) {
|
||||
App.leftMenuItems.dxFind('li[data-init="'+ rid[0] +'"]')?.classList.add('active');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Title or Caption
|
||||
*/
|
||||
static update_Title(name, props, isCaption) {
|
||||
|
||||
props = props || {};
|
||||
|
||||
let target = App.viewEl.dxFind((isCaption ? '.caption' : '.title') + '-' + name);
|
||||
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.label) {
|
||||
target.dxFind(isCaption ? 'h3' : 'h2').textContent = props.label;
|
||||
}
|
||||
|
||||
if (props.icon) {
|
||||
|
||||
let icon = target.dxFind('i');
|
||||
|
||||
if (icon) {
|
||||
icon.className = 'fa' + (props['icon-type'] || 's') + ' fa-'+ props.icon;
|
||||
}
|
||||
else {
|
||||
target.prepend(El('i', { class: 'fa' + (props['icon-type'] || 's') + ' fa-'+ props.icon }) );
|
||||
}
|
||||
}
|
||||
|
||||
if (props.color) {
|
||||
|
||||
target.classList.forEach(cls => {
|
||||
if (cls.startsWith('color-')) {
|
||||
target.classList.remove(cls);
|
||||
}
|
||||
});
|
||||
|
||||
target.className += ' color-' + props.color;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Title El
|
||||
*/
|
||||
static updateTitle(name, props) {
|
||||
App.update_Title(name, props, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Caption El
|
||||
*/
|
||||
static updateCaption(name, props) {
|
||||
App.update_Title(name, props, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set App Menu events
|
||||
*/
|
||||
static initMenuEvents() {
|
||||
|
||||
if (App.menuEventFlag) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Left Logo - Ev Handler
|
||||
*/
|
||||
$('.left-logo').dxOn('click', (_, t) => {
|
||||
if (App.section != App.config.home) {
|
||||
App.initModule(App.config.home, {}, { eTarget: t });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Dropdown Menu - Ev Handler
|
||||
*/
|
||||
App.dropdownMenu.dxOn('click.menu', e => {
|
||||
e.stopPropagation();
|
||||
App.dropdownMenuItems.classList.toggle('hide');
|
||||
});
|
||||
|
||||
App.dropdownMenuItems.dxOn('click.menu', 'li', (_, t) => {
|
||||
|
||||
if (t.dataset.init) {
|
||||
App.initModule(t.dataset.init, {}, { eTarget: t });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Left Menu Trigger - Ev Handlers
|
||||
*/
|
||||
$('.left-menu-trigger').dxOn('click.menu', (e, t) => {
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
t.classList.toggle('active');
|
||||
App.menuSideEl.classList.toggle('toggled');
|
||||
});
|
||||
|
||||
$('.left-menu-handler').dxOn('click.menu', e => {
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
App.menuSideEl.classList.remove('toggled');
|
||||
App.menuSideEl.classList.toggle('opened');
|
||||
});
|
||||
|
||||
$('body').dxOn('click.menu', _ => {
|
||||
App.dropdownMenuItems.classList.add('hide');
|
||||
App.menuSideEl?.classList.remove('opened');
|
||||
});
|
||||
|
||||
/**
|
||||
* Left Menu Items - Ev Handler
|
||||
*/
|
||||
App.leftMenuItems.dxOn('click.menu', 'li', (_, t) => {
|
||||
|
||||
if (t.dxFilter('.submenu')) {
|
||||
|
||||
if (!t.dxFind('.active')) {
|
||||
t.classList.toggle('opened');
|
||||
t.dxFind('ul').dxSlideToggle();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//Overlay.hideModal();
|
||||
App.menuSideEl.classList.remove('opened');
|
||||
|
||||
if (t.dataset.init) {
|
||||
App.initModule(t.dataset.init, {}, { eTarget: t });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Top Tooolbar Back btn - Ev Handler
|
||||
*/
|
||||
$('.top-toolbar').dxOn('click', 'a.back', (_, t) => {
|
||||
|
||||
let back = t.dataset.back;
|
||||
|
||||
if (back == 1 && App.stack) { // In stack
|
||||
App.initModule(App.stack.id, App.stack.vars, { back: App.stack.back, eTarget: t });
|
||||
}
|
||||
else { // Explicit
|
||||
App.initModule(back, {}, { eTarget: t });
|
||||
}
|
||||
});
|
||||
|
||||
App.menuEventFlag = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Menu
|
||||
*/
|
||||
static initMenu() {
|
||||
|
||||
let role = App.role.toString();
|
||||
|
||||
// Menu Selectors
|
||||
|
||||
App.dropdownMenu = $('.dropdown-menu');
|
||||
App.dropdownMenuItems = $('.dropdown-menu').dxFind('ul');
|
||||
App.leftMenuItems = $('.left-menu ul');
|
||||
App.topToolbar = $('.top-toolbar-inner');
|
||||
|
||||
App.dropdownMenuItems.dxHtml('');
|
||||
App.leftMenuItems.dxHtml('');
|
||||
|
||||
if (App.intData.leftmenu) {
|
||||
|
||||
Ut.each(Ut.objVal(App.intData.leftmenu)?.children?.item, dataItem => {
|
||||
|
||||
if (!dataItem.text) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Chech role
|
||||
if (dataItem.role && dataItem.role.split(',').indexOf(role) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let menuItem = App.leftMenuItems.appendChild( El('li', {},
|
||||
El('a', {},
|
||||
El('span', { class: 'menu-item' }, dataItem.text),
|
||||
El('i', { class: 'fa' + (dataItem['icon-type'] || 's') + ' fa-'+ dataItem.icon })
|
||||
)
|
||||
));
|
||||
|
||||
if (dataItem.href) {
|
||||
|
||||
menuItem.firstChild.href = dataItem.href;
|
||||
|
||||
if (dataItem.target) {
|
||||
menuItem.firstChild.target = dataItem.target;
|
||||
}
|
||||
}
|
||||
else if (dataItem.init) {
|
||||
menuItem.dataset.init = dataItem.init;
|
||||
}
|
||||
|
||||
if (dataItem?.children?.item) {
|
||||
|
||||
let submenu = El('ul'),
|
||||
len = 0;
|
||||
|
||||
Ut.each(dataItem.children.item, secDataItem => {
|
||||
|
||||
if (!secDataItem.text) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Chech role
|
||||
if (secDataItem.role && secDataItem.role.split(',').indexOf(role) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
len++;
|
||||
|
||||
let submenuItem = submenu.appendChild( El('li', {},
|
||||
El('a', {},
|
||||
El('span', { class: 'menu-item' }, secDataItem.text),
|
||||
El('i', { class: 'fa' + (secDataItem['icon-type'] || 's') + ' fa-'+ secDataItem.icon })
|
||||
)
|
||||
));
|
||||
|
||||
if (secDataItem.href) {
|
||||
|
||||
submenuItem.firstChild.href = data.href;
|
||||
|
||||
if (secDataItem.target) {
|
||||
submenuItem.firstChild.target = secDataItem.target;
|
||||
}
|
||||
}
|
||||
else if (secDataItem.init) {
|
||||
submenuItem.dataset.init = secDataItem.init;
|
||||
}
|
||||
});
|
||||
|
||||
if (len) {
|
||||
menuItem.classList.add('submenu')
|
||||
menuItem.append(submenu);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (App.intData.usermenu) {
|
||||
|
||||
Ut.each(Ut.objVal(App.intData.usermenu)?.children?.item, dataItem => {
|
||||
|
||||
if (!dataItem.text) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Chech role
|
||||
if (dataItem.role && dataItem.role.split(',').indexOf(role) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let menuItem = App.dropdownMenuItems.appendChild( El('li', {},
|
||||
El('a', {},
|
||||
El('span', { class: 'menu-item' }, dataItem.text),
|
||||
El('i', { class: 'fa' + (dataItem['icon-type'] || 's') + ' fa-'+ dataItem.icon })
|
||||
)
|
||||
));
|
||||
|
||||
if (dataItem.href) {
|
||||
|
||||
menuItem.firstChild.href = dataItem.href;
|
||||
|
||||
if (dataItem.target) {
|
||||
menuItem.firstChild.target = dataItem.target;
|
||||
}
|
||||
}
|
||||
else if (dataItem.init) {
|
||||
menuItem.dataset.init = dataItem.init;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
App.menuFlag = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a specific layout
|
||||
*/
|
||||
static selectLayout(id) {
|
||||
|
||||
$('.app-layout', layout => layout.classList.add('hide'));
|
||||
|
||||
const layout = $('.app-layout[data-id="'+ id +'"]');
|
||||
|
||||
if (!layout) {
|
||||
return;
|
||||
}
|
||||
|
||||
layout.classList.remove('hide');
|
||||
|
||||
App.contentEl = layout.dxFind('.content-wrapper'),
|
||||
App.menuSideEl = layout.dxFind('.left-menu-side');
|
||||
|
||||
if (App.menuSideEl) {
|
||||
App.initMenu();
|
||||
App.initMenuEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import { Rt } from './Rt';
|
||||
import { dxReady } from '../utils/dom';
|
||||
|
||||
/*
|
||||
* Loader Class
|
||||
*/
|
||||
export class Boot {
|
||||
|
||||
// Deb Mode
|
||||
static DEBUG = false;
|
||||
|
||||
// Static App Config
|
||||
static config = {};
|
||||
|
||||
// Static Global Data
|
||||
static data = {};
|
||||
|
||||
// App Loaded state
|
||||
static #started = false;
|
||||
|
||||
// Widget Stack
|
||||
static widgetStack = {};
|
||||
|
||||
// Root data
|
||||
static r = {};
|
||||
|
||||
// Static Section
|
||||
static section = null;
|
||||
static _section = null;
|
||||
|
||||
// Static Section Vars
|
||||
static vars = {};
|
||||
|
||||
static ready(callback) {
|
||||
|
||||
if (Boot.#started) {
|
||||
console.log('Register already called!');
|
||||
return;
|
||||
}
|
||||
|
||||
Boot.#started = true;
|
||||
|
||||
dxReady(() => {
|
||||
|
||||
let dirPath = '/';
|
||||
const h = document.documentElement;
|
||||
|
||||
if (h.classList.contains('app') && location.pathname != '/') {
|
||||
dirPath = location.pathname + '/';
|
||||
}
|
||||
|
||||
Boot.lang = h.getAttribute('lang') ?? 'en';
|
||||
|
||||
Rt.setCsrfToken(h.dxFind('meta[name="csrf-token"]')?.content);
|
||||
|
||||
import(dirPath + 'js/interface.js').then((mod) => {
|
||||
|
||||
if (!mod.intData) {
|
||||
return;
|
||||
}
|
||||
|
||||
Boot.intData = mod.intData;
|
||||
|
||||
callback();
|
||||
|
||||
}).catch((e) => {});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Config Directive
|
||||
*/
|
||||
setConfig(name, value) {
|
||||
Boot.config[name] = value;
|
||||
}
|
||||
|
||||
// Clear Global Data
|
||||
|
||||
clearGlobalData() {
|
||||
Boot.data = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* App Log
|
||||
*/
|
||||
log(msg) {
|
||||
|
||||
if (Boot.DEBUG) {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Standard API Response Codes (Global Object)
|
||||
*/
|
||||
export const Rc = {
|
||||
DONE: 200, // OK
|
||||
CREATED: 201, // Resource created
|
||||
ACCEPTED: 202, // Request accepted (async)
|
||||
NO_CONTENT: 204, // No content to return
|
||||
|
||||
INVALID_PARAMS: 400, // Invalid input parameters
|
||||
NO_SESSION: 401, // Unauthorized / No session
|
||||
FORBIDDEN: 403, // Forbidden (e.g. wrong login)
|
||||
NOT_FOUND: 404, // Resource not found
|
||||
NOT_ALLOWED: 405, // Method not allowed
|
||||
NOT_ACCEPTABLE: 406, // Client does not accept the returned format
|
||||
|
||||
ENTRY_EXISTS: 409, // Entry already exists (conflict)
|
||||
DELETED: 410, // Entry deleted
|
||||
INVALID_CSRF: 419, // Page Expired (non-standard, CSRF failure)
|
||||
|
||||
NOT_MATCH: 422, // Data mismatch / validation failed
|
||||
ACCOUNT_LOCKED: 423, // Account locked
|
||||
EXCEEDED_LIMITS: 429, // Too many requests / rate limit
|
||||
|
||||
NOT_AUTH: 440, // Not authenticated (custom)
|
||||
|
||||
ERROR: 500, // Internal server error
|
||||
BAD_GATEWAY: 502, // Bad gateway from upstream
|
||||
SERV_UNAVAILABLE: 503 // Service temporarily unavailable
|
||||
};
|
||||
+1191
File diff suppressed because it is too large
Load Diff
+207
@@ -0,0 +1,207 @@
|
||||
|
||||
import { Ut } from '../utils/Ut';
|
||||
import { Overlay } from '../widgets/overlay';
|
||||
|
||||
export class Rt {
|
||||
|
||||
static apiUrl = '/backend';
|
||||
static args = null;
|
||||
static csrfToken = null;
|
||||
|
||||
/**
|
||||
* Request Handler
|
||||
*/
|
||||
static request = {
|
||||
get: (action, vars, events, opts) => Rt.smartRequest('GET', action, vars, events, opts),
|
||||
post: (action, vars, events, opts) => Rt.smartRequest('POST', action, vars, events, opts),
|
||||
put: (action, vars, events, opts) => Rt.smartRequest('PUT', action, vars, events, opts),
|
||||
delete: (action, vars, events, opts) => Rt.smartRequest('DELETE', action, vars, events, opts),
|
||||
options: (action, vars, events, opts) => Rt.smartRequest('OPTIONS', action, vars, events, opts),
|
||||
patch: (action, vars, events, opts) => Rt.smartRequest('PATCH', action, vars, events, opts)
|
||||
};
|
||||
|
||||
/**
|
||||
* Async Request Handler
|
||||
*/
|
||||
static call = {
|
||||
get: (action, vars, events, opts) => Rt.asyncRequest('GET', action, vars, events, opts),
|
||||
post: (action, vars, events, opts) => Rt.asyncRequest('POST', action, vars, events, opts),
|
||||
put: (action, vars, events, opts) => Rt.asyncRequest('PUT', action, vars, events, opts),
|
||||
delete: (action, vars, events, opts) => Rt.asyncRequest('DELETE', action, vars, events, opts),
|
||||
options: (action, vars, events, opts) => Rt.asyncRequest('OPTIONS', action, vars, events, opts),
|
||||
patch: (action, vars, events, opts) => Rt.asyncRequest('PATCH', action, vars, events, opts)
|
||||
};
|
||||
|
||||
/**
|
||||
* Set CSRF Token
|
||||
*/
|
||||
static setCsrfToken(csrfToken) {
|
||||
Rt.csrfToken = csrfToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Smart Request
|
||||
*/
|
||||
static smartRequest(method, action, vars, events, opts) {
|
||||
|
||||
events = events || {};
|
||||
opts = { ... { modal: true, loader: false }, ... opts };
|
||||
|
||||
let fdata = new FormData();
|
||||
|
||||
if (vars instanceof FormData) {
|
||||
fdata = vars;
|
||||
}
|
||||
else {
|
||||
Ut.each(vars, (val, key) => fdata.set(key, val));
|
||||
}
|
||||
|
||||
let headers = {};
|
||||
|
||||
if (Rt.csrfToken) {
|
||||
headers = { 'X-CSRF-TOKEN': Rt.csrfToken }
|
||||
}
|
||||
|
||||
if (opts.modal || opts.loader) {
|
||||
Overlay.showModal();
|
||||
}
|
||||
|
||||
if (opts.loader) {
|
||||
Overlay.showLoader();
|
||||
}
|
||||
|
||||
let queryStr = '';
|
||||
|
||||
if (method == 'GET') {
|
||||
|
||||
if (!fdata.entries().next().done) {
|
||||
queryStr = '?' + (new URLSearchParams(fdata)).toString();
|
||||
}
|
||||
|
||||
fdata = null;
|
||||
}
|
||||
|
||||
fetch((Rt.apiUrl ?? '') + action + (opts.args || Rt.args || '') + queryStr, {
|
||||
method: method,
|
||||
body : fdata,
|
||||
cache : 'no-cache',
|
||||
headers: headers,
|
||||
})
|
||||
.then(async response => {
|
||||
const status = response.status;
|
||||
const data = await response.json();
|
||||
return { status, data };
|
||||
})
|
||||
.then(jr => {
|
||||
|
||||
if (opts.modal || opts.loader) {
|
||||
Overlay.hideModal();
|
||||
}
|
||||
|
||||
if (opts.loader) {
|
||||
Overlay.hideLoader();
|
||||
}
|
||||
|
||||
//if (j.code == Rc.INVALID_CSRF_TOKEN || j.code == Rc.NO_SESSION) {
|
||||
// Msg.alert('Session Expired!', () => location.reload());
|
||||
// return;
|
||||
//}
|
||||
|
||||
if (events.done) {
|
||||
events.done(jr.status, jr.data);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
|
||||
if (opts.modal || opts.loader) {
|
||||
Overlay.hideModal();
|
||||
}
|
||||
|
||||
if (opts.loader) {
|
||||
Overlay.hideLoader();
|
||||
}
|
||||
|
||||
if (events.error) {
|
||||
events.error(error);
|
||||
}
|
||||
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Async Request
|
||||
*/
|
||||
static asyncRequest(method, action, vars, opts) {
|
||||
|
||||
opts = { ... { modal: true, loader: false }, ... opts };
|
||||
|
||||
let fdata = new FormData();
|
||||
let headers = {};
|
||||
|
||||
if (vars instanceof FormData) {
|
||||
fdata = vars;
|
||||
}
|
||||
else {
|
||||
Ut.each(vars, (val, key) => fdata.set(key, val));
|
||||
}
|
||||
|
||||
if (Rt.csrfToken) {
|
||||
headers = { 'X-CSRF-TOKEN': Rt.csrfToken }
|
||||
}
|
||||
|
||||
return async(reqOpts) => {
|
||||
|
||||
const updateVars = !! reqOpts.vars;
|
||||
|
||||
reqOpts = { ... {
|
||||
update: true,
|
||||
method: method,
|
||||
action: action,
|
||||
vars: vars,
|
||||
opts: opts
|
||||
}, ... reqOpts };
|
||||
|
||||
if (!reqOpts.update) {
|
||||
fdata = new FormData();
|
||||
}
|
||||
|
||||
if (updateVars) {
|
||||
|
||||
if (reqOpts.vars instanceof FormData) {
|
||||
|
||||
for (const [key, value] of reqOpts.vars.entries()) {
|
||||
fdata.set(key, value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Ut.each(reqOpts.vars, (val, key) => fdata.set(key, val));
|
||||
}
|
||||
}
|
||||
|
||||
let queryStr = '';
|
||||
|
||||
if (reqOpts.method == 'GET') {
|
||||
|
||||
if (!fdata.entries().next().done) {
|
||||
queryStr = '?' + (new URLSearchParams(fdata)).toString();
|
||||
}
|
||||
}
|
||||
|
||||
const resp = await fetch((Rt.apiUrl ?? '') + reqOpts.action + (reqOpts.opts.args || Rt.args || '') + queryStr, {
|
||||
method: reqOpts.method,
|
||||
...(reqOpts.method != 'GET' && { body: fdata }),
|
||||
cache : 'no-cache',
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
try {
|
||||
let data = await resp.json();
|
||||
return { code: resp.status, data: data };
|
||||
|
||||
} catch {
|
||||
throw new Error("Empty or invalid JSON response");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
export class Stack {
|
||||
|
||||
static widgets = {};
|
||||
|
||||
/**
|
||||
* Registers a widget instance in the global registry.
|
||||
*
|
||||
* @param {Object} ref - Widget instance to register.
|
||||
* @returns {void}
|
||||
*/
|
||||
static add(ref) {
|
||||
|
||||
const name = ref.constructor.name;
|
||||
|
||||
Stack.widgets[name] ??= new Map();
|
||||
|
||||
// ref.ekey = crypto.randomUUID();
|
||||
|
||||
ref.ekey = Stack.widgets[name].size;
|
||||
|
||||
Stack.widgets[name].set(ref.ekey, ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a widget instance from the global registry.
|
||||
*
|
||||
* @param {Object} ref - Widget instance to remove.
|
||||
* @returns {void}
|
||||
*/
|
||||
static delete(ref) {
|
||||
|
||||
const name = ref.constructor.name;
|
||||
|
||||
if (!this.widgets[name]?.has(ref.ekey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.widgets[name].delete(ref.ekey);
|
||||
ref.ekey = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
/* ---------------
|
||||
Title
|
||||
/* -------------*/
|
||||
|
||||
.sp-title,
|
||||
.sp-caption {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
.sp-title i,
|
||||
.sp-caption i {
|
||||
flex-shrink: 0;
|
||||
margin-right: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
Links
|
||||
/* -------------*/
|
||||
|
||||
.link {
|
||||
cursor: pointer;
|
||||
color: var(--main-link-color);
|
||||
font-size: 1.18rem;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.link:hover * {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.link.disabled {
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.link i {
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
.link.no-text i {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
List
|
||||
/* -------------*/
|
||||
|
||||
.sp-list {
|
||||
display: block;
|
||||
width: 100%;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.sp-list li {
|
||||
padding: 0 5px;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.sp-list li:last-child {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.sp-list li.item-link {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.sp-list li.item-link:hover {
|
||||
color: var(--theme-widget-color);
|
||||
}
|
||||
|
||||
.sp-list i {
|
||||
margin-right: 15px;
|
||||
flex-shrink: 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
ChipBox
|
||||
/* -------------*/
|
||||
|
||||
.sp-chip {
|
||||
font-size: 12px;
|
||||
background: #e4e9f0;
|
||||
border-radius: 50px;
|
||||
padding: 5px 10px;
|
||||
margin: 4px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sp-chip.big {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.sp-chip i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.sp-chip i.close {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
line-height: 32px;
|
||||
padding-left: 8px;
|
||||
transition: all .1s linear;
|
||||
font-size: 12px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
Status Point
|
||||
/* ---------------*/
|
||||
|
||||
.sp-status {
|
||||
border-radius: 50%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.sp-status.st-0,
|
||||
.sp-status.status-0 {
|
||||
background-color: #CCC;
|
||||
}
|
||||
|
||||
.sp-status.st-1,
|
||||
.sp-status.status-1 {
|
||||
background-color: #2ECC40;
|
||||
}
|
||||
|
||||
.sp-status.status-0,
|
||||
.sp-status.status-1 {
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
Block
|
||||
/* --------------*/
|
||||
|
||||
.sp-block {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: self-start;
|
||||
align-content: start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sp-block .sp-card {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.sp-block.separator {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
margin: 0 0 18px 0;
|
||||
background: rgba(116, 112, 141, 0.4);
|
||||
background: linear-gradient(to right, rgba(116, 112, 141, 0) 0%, rgba(116, 112, 141, 0.4) 50%, rgba(116, 112, 141, 0) 100%);
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
Cards
|
||||
/* --------------*/
|
||||
|
||||
.sp-card {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: start;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sp-card .content-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 10px;
|
||||
/*
|
||||
overflow: hidden;
|
||||
*/
|
||||
}
|
||||
|
||||
.sp-card .container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex: 1;
|
||||
padding: 5px 24px 24px 24px;
|
||||
}
|
||||
|
||||
.sp-card .content-main {
|
||||
padding-bottom: 48px;
|
||||
}
|
||||
|
||||
.sp-card .top-bar {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 18px 24px 18px 24px;
|
||||
}
|
||||
|
||||
.sp-card .top-bar .top-bar-inner {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sp-card .top-bar .title-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sp-card h2.title {
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sp-card p.descr {
|
||||
color: #7a7a7a;
|
||||
font-size: 14px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.sp-card .sp-table {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.sp-card .ic-edit {
|
||||
cursor: pointer;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.sp-card .ic-edit:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.sp-card .tab-menu {
|
||||
display: flex;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
padding: 0 24px 0 24px;
|
||||
}
|
||||
|
||||
.sp-card .tab-menu a {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 22px;
|
||||
padding: 20px 0;
|
||||
color: #4b4b4b;
|
||||
transition: all 0.2s;
|
||||
border-bottom: 3px solid #ededed;
|
||||
}
|
||||
|
||||
.sp-card .tab-menu a.active {
|
||||
border-bottom: 3px solid var(--theme-widget-color);
|
||||
pointer-events: none;
|
||||
color: var(--theme-widget-color);
|
||||
}
|
||||
|
||||
.sp-card .tab-menu span {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
Card Menu
|
||||
/* --------------*/
|
||||
|
||||
.sp-card-menu {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
gap: 20px;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.sp-card-menu .card-menu-item {
|
||||
width: 200px;
|
||||
box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 5px 0px, rgba(0, 0, 0, 0.1) 0px 0px 1px 0px;
|
||||
border-radius: 20px;
|
||||
transition: all 0.2s;
|
||||
padding: 0 15px 15px 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sp-card-menu .card-menu-item:hover {
|
||||
box-shadow: rgba(16, 82, 137, 0.4) 0px 0px 5px 0px, rgba(16, 82, 137, 0.4) 0px 0px 1px 0px;
|
||||
}
|
||||
|
||||
.sp-card-menu .card-menu-item .card-icon-wrapper {
|
||||
height: 80px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sp-card-menu .card-menu-item .card-icon-wrapper i {
|
||||
color: #a5a5a5;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.sp-card-menu .card-menu-item .card-menu-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #4b4b4b;
|
||||
white-space: nowrap;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.sp-card-menu .card-menu-item .card-menu-descr {
|
||||
margin-top: 10px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: #666;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.sp-card-menu .card-menu-item:hover .card-icon-wrapper i,
|
||||
.sp-card-menu .card-menu-item:hover .card-menu-title,
|
||||
.sp-card-menu .card-menu-item:hover .card-menu-descr {
|
||||
color: #105289;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,991 @@
|
||||
:root {
|
||||
|
||||
/* --------------------------
|
||||
Flex Grid standard sizes
|
||||
/* -------------------------*/
|
||||
|
||||
--main-wrapper-width: 92%;
|
||||
--gutters-sizes: 10px;
|
||||
|
||||
/* System colors */
|
||||
|
||||
--white: #FFFFFF;
|
||||
--red: #FF4136;
|
||||
--blue: #0074D9;
|
||||
--green: #228B22;
|
||||
--yellow: #FFDC00;
|
||||
--gray: #AAAAAA;
|
||||
--black: #111111;
|
||||
--carbon: #666666;
|
||||
--orange: #FF851B;
|
||||
--navy: #001f3f;
|
||||
--purple: #B10DC9;
|
||||
--lime: #01FF70;
|
||||
|
||||
/* --------------------------
|
||||
Theme Colors
|
||||
/* -------------------------*/
|
||||
|
||||
--main-font-color: #333333;
|
||||
--main-link-color: #303436;
|
||||
|
||||
--theme-widget-color: #333;
|
||||
|
||||
/* --------------------------
|
||||
Typography Standard
|
||||
/* -------------------------*/
|
||||
|
||||
--font-size-unit: 16px;
|
||||
--main-font-family: Arial, Helvetica, sans-serif;
|
||||
--main-font-size: 0.8125rem;
|
||||
|
||||
--m-f1: var(--f1);
|
||||
--l-f1: var(--m-f1);
|
||||
--xl-f1: var(--l-f1);
|
||||
--xxl-f1: var(--xl-f1);
|
||||
|
||||
--m-f2: var(--f2);
|
||||
--l-f2: var(--m-f2);
|
||||
--xl-f2: var(--l-f2);
|
||||
--xxl-f2: var(--xl-f2);
|
||||
|
||||
--m-f3: var(--f3);
|
||||
--l-f3: var(--m-f3);
|
||||
--xl-f3: var(--l-f3);
|
||||
--xxl-f3: var(--xl-f3);
|
||||
|
||||
--m-f4: var(--f4);
|
||||
--l-f4: var(--m-f4);
|
||||
--xl-f4: var(--l-f4);
|
||||
--xxl-f4: var(--xl-f4);
|
||||
|
||||
--m-f5: var(--f5);
|
||||
--l-f5: var(--m-f5);
|
||||
--xl-f5: var(--l-f5);
|
||||
--xxl-f5: var(--xl-f5);
|
||||
|
||||
--m-f6: var(--f6);
|
||||
--l-f6: var(--m-f6);
|
||||
--xl-f6: var(--l-f6);
|
||||
--xxl-f6: var(--xl-f6);
|
||||
|
||||
--m-f7: var(--f7);
|
||||
--l-f7: var(--m-f7);
|
||||
--xl-f7: var(--l-f7);
|
||||
--xxl-f7: var(--xl-f7);
|
||||
|
||||
--m-f8: var(--f8);
|
||||
--l-f8: var(--m-f8);
|
||||
--xl-f8: var(--l-f8);
|
||||
--xxl-f8: var(--xl-f8);
|
||||
|
||||
--m-f9: var(--f9);
|
||||
--l-f9: var(--m-f9);
|
||||
--xl-f9: var(--l-f9);
|
||||
--xxl-f9: var(--xl-f9);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
Reset
|
||||
/* ---------------*/
|
||||
|
||||
* {
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: var(--main-font-family);
|
||||
font-size: var(--font-size-unit);
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body, p, ul, ol, li, h1, h2, h3, h4, h5, h6, form {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
vertical-align: baseline;
|
||||
border: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: var(--main-font-size);
|
||||
color: var(--main-font-color);
|
||||
}
|
||||
|
||||
article, aside, details, figcaption, figure, footer, header, nav, section, main, summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul { list-style-type: none; }
|
||||
|
||||
textarea{ resize: none; }
|
||||
|
||||
a {
|
||||
text-decoration :none;
|
||||
color: var(--main-link-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[class*='sp-'] {
|
||||
font-family: var(--main-font-family);
|
||||
}
|
||||
|
||||
input::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
ScrollBar
|
||||
/* ---------------*/
|
||||
|
||||
.sp-scrollbar {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: transparent transparent;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.sp-scrollbar:hover {
|
||||
scrollbar-color: #ccc transparent;
|
||||
}
|
||||
|
||||
.sp-scrollbar::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sp-scrollbar::-webkit-scrollbar-thumb {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sp-scrollbar:hover::-webkit-scrollbar-thumb {
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
/* -----------------
|
||||
ToolTip
|
||||
/* ----------------*/
|
||||
|
||||
[data-tooltip] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[data-tooltip]:hover::before,
|
||||
[data-tooltip-left]:hover::before,
|
||||
[data-tooltip-right]:hover::before,
|
||||
[data-tooltip-bottom]:hover::before {
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
content: attr(data-tooltip);
|
||||
background: #fff;
|
||||
color: #212121;
|
||||
padding: 0 10px;
|
||||
height: 25px;
|
||||
border-radius: 5px;
|
||||
font-weight: 600;
|
||||
font-family:'raleway', Arial, sans-serif;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
font-size: 13px;
|
||||
top: -30px;
|
||||
left: -10px;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
[data-tooltip-left]:hover::before {
|
||||
content: attr(data-tooltip-left);
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
transform: translateX(-102%);
|
||||
}
|
||||
|
||||
[data-tooltip-right]:hover::before {
|
||||
content: attr(data-tooltip-right);
|
||||
top: 0;
|
||||
left: auto;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
transform: translateX(102%);
|
||||
}
|
||||
|
||||
[data-tooltip-bottom]:hover::before {
|
||||
content: attr(data-tooltip-bottom);
|
||||
top: auto;
|
||||
bottom: -30px;
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-blue::before,
|
||||
[data-tooltip-left].tooltip-color-blue::before,
|
||||
[data-tooltip-right].tooltip-color-blue::before,
|
||||
[data-tooltip-bottom].tooltip-color-blue::before {
|
||||
background-color: var(--blue);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-blue.transparent::before,
|
||||
[data-tooltip-left].tooltip-color-blue.transparent::before,
|
||||
[data-tooltip-right].tooltip-color-blue.transparent::before,
|
||||
[data-tooltip-bottom].tooltip-color-blue.transparent::before {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--blue);
|
||||
color: var(--blue);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-red::before,
|
||||
[data-tooltip-left].tooltip-color-red::before,
|
||||
[data-tooltip-right].tooltip-color-red::before,
|
||||
[data-tooltip-bottom].tooltip-color-red::before {
|
||||
background-color: var(--red);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-red.transparent::before,
|
||||
[data-tooltip-left].tooltip-color-red.transparent::before,
|
||||
[data-tooltip-right].tooltip-color-red.transparent::before,
|
||||
[data-tooltip-bottom].tooltip-color-red.transparent::before {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--red);
|
||||
color: var(--red);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-orange::before,
|
||||
[data-tooltip-left].tooltip-color-orange::before,
|
||||
[data-tooltip-right].tooltip-color-orange::before,
|
||||
[data-tooltip-bottom].tooltip-color-orange::before {
|
||||
background-color: var(--orange);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-orange.transparent::before,
|
||||
[data-tooltip-left].tooltip-color-orange.transparent::before,
|
||||
[data-tooltip-right].tooltip-color-orange.transparent::before,
|
||||
[data-tooltip-bottom].tooltip-color-orange.transparent::before {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--orange);
|
||||
color: var(--orange);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-green::before,
|
||||
[data-tooltip-left].tooltip-color-green::before,
|
||||
[data-tooltip-right].tooltip-color-green::before,
|
||||
[data-tooltip-bottom].tooltip-color-green::before {
|
||||
background-color: var(--green);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-green.transparent::before,
|
||||
[data-tooltip-left].tooltip-color-green.transparent::before,
|
||||
[data-tooltip-right].tooltip-color-green.transparent::before,
|
||||
[data-tooltip-bottom].tooltip-color-green.transparent::before {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--green);
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-navy::before,
|
||||
[data-tooltip-left].tooltip-color-navy::before,
|
||||
[data-tooltip-right].tooltip-color-navy::before,
|
||||
[data-tooltip-bottom].tooltip-color-navy::before {
|
||||
background-color: var(--navy);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-navy.transparent::before,
|
||||
[data-tooltip-left].tooltip-color-navy.transparent::before,
|
||||
[data-tooltip-right].tooltip-color-navy.transparent::before,
|
||||
[data-tooltip-bottom].tooltip-color-navy.transparent::before {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--navy);
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-black::before,
|
||||
[data-tooltip-left].tooltip-color-black::before,
|
||||
[data-tooltip-right].tooltip-color-black::before,
|
||||
[data-tooltip-bottom].tooltip-color-black::before {
|
||||
background-color: var(--black);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-black.transparent::before,
|
||||
[data-tooltip-left].tooltip-color-black.transparent::before,
|
||||
[data-tooltip-right].tooltip-color-black.transparent::before,
|
||||
[data-tooltip-bottom].tooltip-color-black.transparent::before {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--black);
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-carbon::before,
|
||||
[data-tooltip-left].tooltip-color-carbon::before,
|
||||
[data-tooltip-right].tooltip-color-carbon::before,
|
||||
[data-tooltip-bottom].tooltip-color-carbon::before {
|
||||
background-color: var(--carbon);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-carbon.transparent::before,
|
||||
[data-tooltip-left].tooltip-color-carbon.transparent::before,
|
||||
[data-tooltip-right].tooltip-color-carbon.transparent::before,
|
||||
[data-tooltip-bottom].tooltip-color-carbon.transparent::before {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--carbon);
|
||||
color: var(--carbon);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-gray::before,
|
||||
[data-tooltip-left].tooltip-color-gray::before,
|
||||
[data-tooltip-right].tooltip-color-gray::before,
|
||||
[data-tooltip-bottom].tooltip-color-gray::before {
|
||||
background-color: var(--gray);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-gray.transparent::before,
|
||||
[data-tooltip-left].tooltip-color-gray.transparent::before,
|
||||
[data-tooltip-right].tooltip-color-gray.transparent::before,
|
||||
[data-tooltip-bottom].tooltip-color-gray.transparent::before {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--gray);
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-white::before,
|
||||
[data-tooltip-left].tooltip-color-white::before,
|
||||
[data-tooltip-right].tooltip-color-white::before,
|
||||
[data-tooltip-bottom].tooltip-color-white::before {
|
||||
background-color: var(--white);
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
[data-tooltip].tooltip-color-white.transparent::before,
|
||||
[data-tooltip-left].tooltip-color-white.transparent::before,
|
||||
[data-tooltip-right].tooltip-color-white.transparent::before,
|
||||
[data-tooltip-bottom].tooltip-color-white.transparent::before {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--white);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
Buttons
|
||||
/* --------------*/
|
||||
|
||||
.sp-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
background-color: var(--theme-widget-color);
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.0285rem;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
height: 40px;
|
||||
padding: 0 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sp-button.small {
|
||||
height: 24px;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.sp-button.transparent {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.sp-button.ui-color-white {
|
||||
background-color: var(--white);
|
||||
color: var(--carbon);
|
||||
border: 1px solid #e4e9f0;
|
||||
}
|
||||
|
||||
.sp-button:disabled,
|
||||
.sp-button.disabled,
|
||||
.sp-button.disabled:hover {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.sp-button:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.sp-button i.icon-left {
|
||||
margin-right: 8px;
|
||||
order: 0;
|
||||
}
|
||||
|
||||
.sp-button i.icon-right {
|
||||
margin-left: 8px;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.sp-button.icon-only i.icon-left {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.sp-button.icon-only i.icon-right {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.sp-button span {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
/* ----------------------
|
||||
Forms And Block
|
||||
/* ---------------------*/
|
||||
|
||||
.sp-form {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: self-start;
|
||||
align-content: start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
padding: 0 4px;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-field.inline {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-field .field-label {
|
||||
margin-bottom: 8px;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.form-field.field-radio .field-label,
|
||||
.form-field.field-checkbox .field-label {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.checkbox-control label {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.form-field .input-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.form-field.field-text .input-wrapper,
|
||||
.form-field.field-password .input-wrapper,
|
||||
.form-field.field-select .input-wrapper {
|
||||
border: 1px solid #e4e9f0;
|
||||
border-radius: 4px;
|
||||
height: 40px;
|
||||
transition: border-color 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.form-field.field-text .input-wrapper:not(.form-field-error):focus-within,
|
||||
.form-field.field-password .input-wrapper:not(.form-field-error):focus-within,
|
||||
.form-field.field-select .input-wrapper:not(.form-field-error):focus-within {
|
||||
border-color: rgba(16, 82, 137, 0.4);
|
||||
}
|
||||
|
||||
.form-field.field-text i,
|
||||
.form-field.field-password i,
|
||||
.form-field.field-select i {
|
||||
flex-shrink: 0;
|
||||
padding: 0 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.form-field.form-field-error .input-wrapper {
|
||||
border-bottom-color: red;
|
||||
}
|
||||
|
||||
.form-field.form-field-error textarea {
|
||||
border-bottom-color: red;
|
||||
}
|
||||
|
||||
.form-field.field-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.form-field.field-info .label-name {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.form-field.field-info .label-value {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.form-field.field-info .label-value.text-wrap {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.form-field.field-info i {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.form-field.field-separator {
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.sp-form .sp-button.bottom {
|
||||
align-self: end;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.block-buttons {
|
||||
padding-top: 20px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.form-field .icon-left {
|
||||
order: 0;
|
||||
}
|
||||
|
||||
.form-field .icon-right {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.form-field .icon-clear {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-field .icon-left.disabled,
|
||||
.form-field .icon-right.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.form-field i.icon-clear:after {
|
||||
display: block;
|
||||
content: '';
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNDkyIDQ5MiI+PGcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMzAwLjIgMjQ2TDQ4NC4xIDYyYzUuMS01LjEgNy45LTExLjggNy45LTE5IDAtNy4yLTIuOC0xNC03LjktMTlMNDY4IDcuOWMtNS4xLTUuMS0xMS44LTcuOS0xOS03LjkgLTcuMiAwLTE0IDIuOC0xOSA3LjlMMjQ2IDE5MS44IDYyIDcuOWMtNS4xLTUuMS0xMS44LTcuOS0xOS03LjkgLTcuMiAwLTE0IDIuOC0xOSA3LjlMNy45IDI0Yy0xMC41IDEwLjUtMTAuNSAyNy42IDAgMzguMUwxOTEuOCAyNDYgNy45IDQzMGMtNS4xIDUuMS03LjkgMTEuOC03LjkgMTkgMCA3LjIgMi44IDE0IDcuOSAxOWwxNi4xIDE2LjFjNS4xIDUuMSAxMS44IDcuOSAxOSA3LjkgNy4yIDAgMTQtMi44IDE5LTcuOWwxODQtMTg0IDE4NCAxODRjNS4xIDUuMSAxMS44IDcuOSAxOSA3LjloMGM3LjIgMCAxNC0yLjggMTktNy45bDE2LjEtMTYuMWM1LjEtNS4xIDcuOS0xMS44IDcuOS0xOSAwLTcuMi0yLjgtMTQtNy45LTE5TDMwMC4yIDI0NnoiIGRhdGEtb3JpZ2luYWw9IiMwMDAwMDAiIGZpbGw9IiM3ODc0NzQiLz48L2c+PC9zdmc+) no-repeat 96% 50%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-size: 10px 10px;
|
||||
}
|
||||
|
||||
.form-field .input-bar {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-field .input-bar:before {
|
||||
content: "";
|
||||
height: 1px;
|
||||
width: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
background: var(--theme-widget-color);
|
||||
transition: 300ms ease all;
|
||||
left: 0%;
|
||||
}
|
||||
|
||||
.sp-button.btn-cancel {
|
||||
background-color: transparent;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.label-value {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.label-value p {
|
||||
font-weight: bold;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
/* -----------------
|
||||
Checkbox Ui
|
||||
/* ----------------*/
|
||||
|
||||
.sp-control {
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sp-control label {
|
||||
display: block;
|
||||
flex-basis: auto;
|
||||
padding-right: 20px;
|
||||
line-height: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sp-control input{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sp-control .ctrl-indicator{
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
background: #d2d9e5;
|
||||
border-radius: 3px;
|
||||
position: relative;
|
||||
margin-right: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sp-control .ctrl-indicator::after {
|
||||
display: block;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.sp-control label:hover input ~ .ctrl-indicator,
|
||||
.sp-control input:focus ~ .ctrl-indicator {
|
||||
background: #b8beca;
|
||||
}
|
||||
|
||||
.sp-control input:checked ~ .ctrl-indicator {
|
||||
background: var(--theme-widget-color);
|
||||
}
|
||||
|
||||
.sp-control label:hover input:not([disabled]):checked ~ .ctrl-indicator,
|
||||
.sp-control input:checked:focus ~ .ctrl-indicator {
|
||||
background: var(--theme-widget-color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.sp-control input:disabled ~ .ctrl-indicator {
|
||||
pointer-events: none;
|
||||
opacity: 0.6;
|
||||
background: #eef0f4;
|
||||
}
|
||||
|
||||
.sp-control input:checked ~ .ctrl-indicator:after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sp-control.checkbox-control input:checked ~ .ctrl-indicator:after {
|
||||
width: 6px;
|
||||
height: 10px;
|
||||
transform: rotate(45deg);
|
||||
border: solid #fff;
|
||||
border-width: 0 2px 2px 0;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.sp-control input:disabled ~ .ctrl-indicator:after {
|
||||
border-color: #7b7b7b;
|
||||
}
|
||||
|
||||
.sp-control.radio-control .ctrl-indicator {
|
||||
border-radius: 50% !important;
|
||||
}
|
||||
|
||||
.sp-control.radio-control .ctrl-indicator:after {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50% !important;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.sp-control.radio-control input:disabled ~ .ctrl-indicator:after {
|
||||
background: #7b7b7b;
|
||||
}
|
||||
|
||||
/* ----------------------
|
||||
Input Form Control
|
||||
/* ---------------------*/
|
||||
|
||||
.sp-form-control {
|
||||
flex: 1;
|
||||
padding: 0 12px;
|
||||
font-weight: 400;
|
||||
color: #74708d;
|
||||
background-color: #fff;
|
||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.no-fit .sp-form-control {
|
||||
width: auto;
|
||||
min-width: 40%;
|
||||
}
|
||||
|
||||
.max-fit .sp-form-control {
|
||||
max-width: 220px;
|
||||
}
|
||||
|
||||
.sp-form-control[data-cancelable="1"] {
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
.sp-form-control::placeholder {
|
||||
color: #a9a9a9;
|
||||
}
|
||||
|
||||
select.sp-form-control {
|
||||
padding-right: 24px;
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNDkyIDQ5MiI+PGcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNDg0LjEgMTI1bC0xNi4xLTE2LjJjLTUuMS01LjEtMTEuOC03LjktMTktNy45IC03LjIgMC0xNCAyLjgtMTkgNy45bC0xODMuOCAxODMuOEw2Mi4xIDEwOC42Yy01LjEtNS4xLTExLjgtNy45LTE5LTcuOXMtMTQgMi44LTE5IDcuOWwtMTYuMSAxNi4xYy0xMC41IDEwLjUtMTAuNSAyNy42IDAgMzguMWwyMTkuMSAyMTkuOWM1LjEgNS4xIDExLjggOC42IDE5LjEgOC42aDAuMWM3LjIgMCAxNC0zLjYgMTktOC42bDIxOC45LTIxOS4zYzUuMS01LjEgNy45LTEyIDcuOS0xOS4yQzQ5MiAxMzYuOSA0ODkuMiAxMzAgNDg0LjEgMTI1eiIgZGF0YS1vcmlnaW5hbD0iIzAwMDAwMCIgZmlsbD0iIzc0NzQ3NCIvPjwvZz48L3N2Zz4=) no-repeat;
|
||||
background-position: calc(100% - 10px) 50%;
|
||||
background-size: 10px 10px;
|
||||
}
|
||||
|
||||
.field-color .input-color-wrapper {
|
||||
width: 50px;
|
||||
height: 25px;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--gray);
|
||||
}
|
||||
|
||||
.field-color input {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
cursor: pointer;
|
||||
transform: translate(-25%, -25%);
|
||||
}
|
||||
|
||||
.field-range input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.field-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
textarea.sp-form-control {
|
||||
height: 130px;
|
||||
padding: 12px;
|
||||
font-family: var(--main-font-family);
|
||||
border: 1px solid #e4e9f0;
|
||||
border-radius: 4px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
textarea.sp-form-control[rows] {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
textarea.sp-form-control[data-expand] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sp-form-control:disabled {
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
/* -----------------
|
||||
RadioBox
|
||||
/* ----------------*/
|
||||
|
||||
.sp-radio-box {
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.sp-radio-box input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sp-radio-box label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.sp-radio-box .ctrl-indicator {
|
||||
height: 38px;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding: 0 16px;
|
||||
cursor: pointer;
|
||||
border: 1px solid #e4e9f0;
|
||||
color: var(--black);
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.sp-radio-box label:first-child .ctrl-indicator {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
.sp-radio-box label:last-child .ctrl-indicator {
|
||||
border-radius: 0 4px 4px 0;
|
||||
border-right: 1px solid #e4e9f0;
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-gray {
|
||||
background-color: var(--gray);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-green {
|
||||
background-color: var(--green);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-red {
|
||||
background-color: var(--red);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-blue {
|
||||
background-color: var(--blue);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-orange {
|
||||
background-color: var(--orange);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-yellow {
|
||||
background-color: var(--yellow);
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-navy {
|
||||
background-color: var(--navy);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-purple {
|
||||
background-color: var(--purple);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-lime {
|
||||
background-color: var(--lime);
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-black {
|
||||
background-color: var(--black);
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-default,
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator.label-color-white {
|
||||
background-color: #eee;
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.sp-radio-box input:checked ~ .ctrl-indicator {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* ---------------------
|
||||
Switch Buttons
|
||||
/* -------------------*/
|
||||
|
||||
.sp-switch {
|
||||
position: relative;
|
||||
width: 52px;
|
||||
height: 30px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sp-switch.inline-block {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.sp-switch .s-slider {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
background-color: #dee2e6;
|
||||
align-items: center;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.sp-switch.round-switch .s-slider {
|
||||
border-radius: 32px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sp-switch .s-slider:before {
|
||||
width: 24px;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
display: block;
|
||||
content: '';
|
||||
transition: .3s;
|
||||
}
|
||||
|
||||
.sp-switch.round-switch .s-slider::before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.sp-switch input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sp-switch input:checked + .s-slider {
|
||||
background-color:var(--theme-widget-color);
|
||||
}
|
||||
|
||||
.sp-switch input:checked + .s-slider::before {
|
||||
transform: translateX(21px);
|
||||
}
|
||||
|
||||
/* -------------------------
|
||||
Zoom input on safari
|
||||
/* -----------------------*/
|
||||
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
|
||||
select, textarea, input {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user