first commit

This commit is contained in:
2025-11-25 01:21:34 +02:00
commit 4af0db8263
84 changed files with 18906 additions and 0 deletions
+770
View File
@@ -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();
}
}
}
+93
View File
@@ -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);
}
}
}
+30
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+207
View File
@@ -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");
}
}
}
}
+41
View File
@@ -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;
}
}
+345
View File
@@ -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
+991
View File
@@ -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;
}
}