✨ feat(break-change): full support gradio-3.23.0
parent
9509e3d6eb
commit
e47578c9f1
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 MiB |
|
|
@ -0,0 +1,10 @@
|
|||
const gulp = require("gulp");
|
||||
const less = require("gulp-less");
|
||||
|
||||
gulp.task("less", function () {
|
||||
return gulp.src("src/theme/*.less").pipe(less()).pipe(gulp.dest("./"));
|
||||
});
|
||||
|
||||
gulp.task("watch", function () {
|
||||
gulp.watch("src/theme/**/*", gulp.parallel("less"));
|
||||
});
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
class InjectBackground{
|
||||
constructor(){
|
||||
this.image;
|
||||
}
|
||||
async init(selector="div[class^=mx-auto][class*=container]"){
|
||||
this.element = undefined
|
||||
while(true){
|
||||
this.element = gradioApp().querySelector(selector)
|
||||
if (this.element){
|
||||
break
|
||||
}
|
||||
await delay(500)
|
||||
}
|
||||
this.element.setAttribute("style", "background-image: url(file=static/background.png); background-size: contain; background-attachment: fixed; background-position: center; background-repeat: no-repeat")
|
||||
}
|
||||
removeStyle(){
|
||||
this.element.removeStyle()
|
||||
}
|
||||
removeImage(){
|
||||
this.element.style['background-image'] = ""
|
||||
}
|
||||
updateImage(path){
|
||||
this.element.style['background-image'] = `url(file=${path})`
|
||||
}
|
||||
//destroy not necessarily needed at this time, it's to keep the api similar
|
||||
destroy(){
|
||||
this.removeStyle()
|
||||
}
|
||||
async refreshImage(file_name){
|
||||
setTimeout(location.reload(), 200)
|
||||
//this.updateImage("static/background.png")
|
||||
console.log(file_name)
|
||||
return file_name
|
||||
}
|
||||
}
|
||||
/*
|
||||
element.style {
|
||||
background-image: url(file=logo.png);
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
background-position: center;
|
||||
}
|
||||
*/
|
||||
|
||||
let injectBackground = new InjectBackground()
|
||||
async function registerInjectHandler(){
|
||||
await injectBackground.init()
|
||||
while(true){
|
||||
if(injectBackground.element){
|
||||
break
|
||||
}
|
||||
await delay(500)
|
||||
}
|
||||
qkcssImagemap.injectBackground = injectBackground
|
||||
}
|
||||
|
||||
function delay(ms){return new Promise(resolve => setTimeout(resolve, ms))}
|
||||
document.addEventListener("DOMContentLoaded", async function (){await registerInjectHandler()})
|
||||
|
|
@ -1,22 +1,14 @@
|
|||
class FaviconHandler {
|
||||
static setFavicon() {
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'icon';
|
||||
link.type = 'image/svg+xml';
|
||||
link.href = getComputedStyle(gradioApp().querySelector('.icon-container')).backgroundImage.replace(/^url\("|"\)$/g, '');
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
}
|
||||
static observeGradioApp() {
|
||||
const observer = new MutationObserver(() => {
|
||||
const iconContainer = gradioApp().querySelector('.icon-container');
|
||||
if (iconContainer) {
|
||||
observer.disconnect();
|
||||
FaviconHandler.setFavicon();
|
||||
}
|
||||
});
|
||||
observer.observe(gradioApp(), { childList: true, subtree: true });
|
||||
}
|
||||
static setFavicon() {
|
||||
const link = document.createElement("link");
|
||||
link.rel = "icon";
|
||||
link.type = "image/svg+xml";
|
||||
link.href =
|
||||
"https://gw.alipayobjects.com/zos/bmw-prod/51a51720-8a30-4430-b6c9-be5712364f04.svg";
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
FaviconHandler.observeGradioApp();
|
||||
FaviconHandler.setFavicon();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,219 @@
|
|||
class Converter {
|
||||
static round(value) {
|
||||
return Math.round(value * 10000) / 10000;
|
||||
}
|
||||
|
||||
static convertStr(srt) {
|
||||
return srt.replace(/:/g, ":").replace(/(/g, "(").replace(/)/g, ")");
|
||||
}
|
||||
|
||||
static convertStr2Array(str) {
|
||||
// 匹配各种括号中的内容,包括括号本身
|
||||
const bracketRegex = /(\(|\)|<|>|\[|\])/g;
|
||||
|
||||
// 将字符串按照各种括号分割成数组
|
||||
const splitByBracket = (str) => {
|
||||
const arr = [];
|
||||
let start = 0;
|
||||
let depth = 0;
|
||||
let match;
|
||||
while ((match = bracketRegex.exec(str)) !== null) {
|
||||
if (depth === 0 && match.index > start) {
|
||||
arr.push(str.substring(start, match.index));
|
||||
start = match.index;
|
||||
}
|
||||
if (match[0] === "(" || match[0] === "<" || match[0] === "[") {
|
||||
depth++;
|
||||
} else if (match[0] === ")" || match[0] === ">" || match[0] === "]") {
|
||||
depth--;
|
||||
}
|
||||
if (depth === 0) {
|
||||
arr.push(str.substring(start, match.index + 1));
|
||||
start = match.index + 1;
|
||||
}
|
||||
}
|
||||
if (start < str.length) {
|
||||
arr.push(str.substring(start));
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
// 将字符串按照逗号和各种括号分割成数组
|
||||
const splitByComma = (str) => {
|
||||
const arr = [];
|
||||
let start = 0;
|
||||
let inBracket = false;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
if (str[i] === "," && !inBracket) {
|
||||
arr.push(str.substring(start, i).trim());
|
||||
start = i + 1;
|
||||
} else if (str[i].match(bracketRegex)) {
|
||||
inBracket = !inBracket;
|
||||
}
|
||||
}
|
||||
arr.push(str.substring(start).trim());
|
||||
return arr;
|
||||
};
|
||||
|
||||
// 清洗字符串并输出数组
|
||||
const cleanStr = (str) => {
|
||||
let arr = splitByBracket(str);
|
||||
arr = arr.flatMap((s) => splitByComma(s));
|
||||
return arr.filter((s) => s !== "");
|
||||
};
|
||||
|
||||
return cleanStr(str)
|
||||
.filter((item) => {
|
||||
const pattern = /^[,\s, ]+$/;
|
||||
return !pattern.test(item);
|
||||
})
|
||||
.filter(Boolean)
|
||||
.sort((a, b) => {
|
||||
return a.includes("<") && !b.includes("<")
|
||||
? 1
|
||||
: b.includes("<") && !a.includes("<")
|
||||
? -1
|
||||
: 0;
|
||||
});
|
||||
}
|
||||
|
||||
static convertArray2Str(array) {
|
||||
const newArray = array.map((item) => {
|
||||
if (item.includes("<")) return item;
|
||||
const newItem = item
|
||||
.replace(/\s+/g, " ")
|
||||
.replace([/\,|\.|\。/g, ","])
|
||||
.replace([/\“|\‘|\”|\"|\\|\//g, ""])
|
||||
.replace(/\, /g, ",")
|
||||
.replace(/\,\,/g, ",")
|
||||
.replace(/\,/g, ", ");
|
||||
return Converter.convertStr2Array(newItem).join(", ");
|
||||
});
|
||||
return newArray.join(", ");
|
||||
}
|
||||
|
||||
static convert(input) {
|
||||
const re_attention = /\{|\[|\}|\]|[^\{\}\[\]]+/gmu;
|
||||
|
||||
let text = Converter.convertStr(input);
|
||||
text = Converter.convertStr2Array(text);
|
||||
text = Converter.convertArray2Str(text);
|
||||
|
||||
let res = [];
|
||||
|
||||
const curly_bracket_multiplier = 1.05;
|
||||
const square_bracket_multiplier = 1 / 1.05;
|
||||
|
||||
const brackets = {
|
||||
"{": { stack: [], multiplier: curly_bracket_multiplier },
|
||||
"[": { stack: [], multiplier: square_bracket_multiplier },
|
||||
};
|
||||
|
||||
function multiply_range(start_position, multiplier) {
|
||||
for (let pos = start_position; pos < res.length; pos++) {
|
||||
res[pos][1] = Converter.round(res[pos][1] * multiplier);
|
||||
}
|
||||
}
|
||||
|
||||
for (const match of text.matchAll(re_attention)) {
|
||||
let word = match[0];
|
||||
|
||||
if (word in brackets) {
|
||||
brackets[word].stack.push(res.length);
|
||||
} else if (word == "}" || word == "]") {
|
||||
const bracket = brackets[word === "}" ? "{" : "["];
|
||||
if (bracket.stack.length > 0) {
|
||||
multiply_range(bracket.stack.pop(), bracket.multiplier);
|
||||
}
|
||||
} else {
|
||||
res.push([word, 1.0]);
|
||||
}
|
||||
}
|
||||
|
||||
for (const bracketType in brackets) {
|
||||
for (const pos of brackets[bracketType].stack) {
|
||||
multiply_range(pos, brackets[bracketType].multiplier);
|
||||
}
|
||||
}
|
||||
|
||||
if (res.length == 0) {
|
||||
res = [["", 1.0]];
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
while (i + 1 < res.length) {
|
||||
if (res[i][1] == res[i + 1][1]) {
|
||||
res[i][0] += res[i + 1][0];
|
||||
res.splice(i + 1, 1);
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let result = "";
|
||||
for (const [word, value] of res) {
|
||||
result += value === 1.0 ? word : `(${word}:${value.toString()})`;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static dispatchInputEvent(target) {
|
||||
let inputEvent = new Event("input");
|
||||
Object.defineProperty(inputEvent, "target", { value: target });
|
||||
target.dispatchEvent(inputEvent);
|
||||
}
|
||||
|
||||
static onClickConvert(type) {
|
||||
const default_prompt = "";
|
||||
const default_negative = "";
|
||||
|
||||
const prompt = gradioApp().querySelector(
|
||||
`#${type}_prompt > label > textarea`
|
||||
);
|
||||
const result = Converter.convert(prompt.value);
|
||||
prompt.value =
|
||||
result.match(/^masterpiece, best quality,/) === null
|
||||
? default_prompt + result
|
||||
: result;
|
||||
Converter.dispatchInputEvent(prompt);
|
||||
const negprompt = gradioApp().querySelector(
|
||||
`#${type}_neg_prompt > label > textarea`
|
||||
);
|
||||
const negResult = Converter.convert(negprompt.value);
|
||||
negprompt.value =
|
||||
negResult.match(/^lowres,/) === null
|
||||
? negResult.length === 0
|
||||
? default_negative
|
||||
: default_negative + negResult
|
||||
: negResult;
|
||||
Converter.dispatchInputEvent(negprompt);
|
||||
}
|
||||
|
||||
static createButton(id, innerHTML, onClick) {
|
||||
const button = document.createElement("button");
|
||||
button.id = id;
|
||||
button.type = "button";
|
||||
button.innerHTML = innerHTML;
|
||||
button.className = "lg secondary gradio-button tool svelte-1ipelgc";
|
||||
button.addEventListener("click", onClick);
|
||||
return button;
|
||||
}
|
||||
|
||||
static addPromptButton(type) {
|
||||
const generateBtn = gradioApp().querySelector(`#${type}_generate`);
|
||||
const actionsColumn = gradioApp().querySelector(`#${type}_style_create`);
|
||||
const nai2local = gradioApp().querySelector(`#${type}_nai2localconvert`);
|
||||
if (!generateBtn || !actionsColumn || nai2local) return;
|
||||
const convertBtn = Converter.createButton(
|
||||
`${type}_nai2localconvert`,
|
||||
"🪄",
|
||||
() => Converter.onClickConvert(type)
|
||||
);
|
||||
actionsColumn.parentNode.append(convertBtn);
|
||||
}
|
||||
}
|
||||
|
||||
onUiUpdate(() => {
|
||||
Converter.addPromptButton("txt2img");
|
||||
Converter.addPromptButton("img2img");
|
||||
});
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
class MatrixEffect{
|
||||
constructor(){
|
||||
this.matrixCanvas = document.createElement("canvas")
|
||||
this.matrixCanvas.setAttribute("style", "position: fixed;")
|
||||
gradioApp().querySelector("div[class*=container]:not([class^=modal])").insertAdjacentElement('afterbegin', this.matrixCanvas)
|
||||
}
|
||||
|
||||
async initialize(){
|
||||
while(!gradioApp().querySelector('canvas')){
|
||||
await delay(300)
|
||||
}
|
||||
// Initialising the canvas
|
||||
this.ctx = this.matrixCanvas.getContext('2d');
|
||||
|
||||
// Setting the width and height of the canvas
|
||||
this.matrixCanvas.width = window.innerWidth;
|
||||
this.matrixCanvas.height = window.innerHeight;
|
||||
|
||||
// Setting up the letters
|
||||
this.letters = 'ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ';
|
||||
this.letters = this.letters.split('');
|
||||
|
||||
// Setting up the columns
|
||||
this.fontSize = 10,
|
||||
this.columns = this.matrixCanvas.width / this.fontSize;
|
||||
|
||||
// Setting up the drops
|
||||
this.drops = [];
|
||||
for (var i = 0; i < this.columns; i++) {
|
||||
this.drops[i] = 1;
|
||||
}
|
||||
this.running = true;
|
||||
|
||||
//timer
|
||||
this.then = Date.now();
|
||||
this.fps = 20;
|
||||
this.fpsInterval = 1000/this.fps;
|
||||
|
||||
|
||||
// Setting up the draw function
|
||||
this.draw = () => {
|
||||
this.now = Date.now();
|
||||
this.elapsed = this.now - this.then;
|
||||
if (this.elapsed > this.fpsInterval){
|
||||
this.then = this.now - (this.elapsed % this.fpsInterval);
|
||||
|
||||
this.ctx.fillStyle = 'rgba(0, 0, 0, .1)';
|
||||
this.ctx.fillRect(0, 0, this.matrixCanvas.width, this.matrixCanvas.height);
|
||||
for (var i = 0; i < this.drops.length; i++) {
|
||||
text = this.letters[Math.floor(Math.random() * this.letters.length)];
|
||||
this.ctx.fillStyle = '#0f0';
|
||||
this.ctx.fillText(text, i * this.fontSize, this.drops[i] * this.fontSize);
|
||||
this.drops[i]++;
|
||||
if (this.drops[i] * this.fontSize > this.matrixCanvas.height && Math.random() > .95) {
|
||||
this.drops[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.running){
|
||||
requestAnimationFrame(this.draw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroy(){
|
||||
this.running = false;
|
||||
//clearInterval(this.Interval)
|
||||
this.matrixCanvas.remove()
|
||||
}
|
||||
}
|
||||
|
||||
let matrixEffect;
|
||||
|
||||
async function registerMatrixToHandler(){
|
||||
await delay(1000);
|
||||
while(qkcssFXMap == undefined){
|
||||
await delay(500)
|
||||
}
|
||||
qkcssFXMap["matrixfx"] = [launchMatrixEffect, matrixEffect];
|
||||
}
|
||||
|
||||
async function launchMatrixEffect(){
|
||||
await delay(1000)
|
||||
while (!gradioApp().querySelector("div[class*=container]:not([class^=modal])")){
|
||||
await delay(300);
|
||||
}
|
||||
// Loop the animation
|
||||
matrixEffect = new MatrixEffect()
|
||||
//Shortciruited it
|
||||
qkcssFXMap["matrixfx"][1] = matrixEffect
|
||||
await delay(500)
|
||||
matrixEffect.initialize()
|
||||
matrixEffect.Interval = matrixEffect.draw();
|
||||
//matrixEffect.Interval = setInterval(matrixEffect.draw, 33);
|
||||
}
|
||||
|
||||
function delay(ms){return new Promise(resolve => setTimeout(resolve, ms))}
|
||||
//document.addEventListener("DOMContentLoaded", async function() {await launchMatrixEffect()})
|
||||
document.addEventListener("DOMContentLoaded", async function() {await registerMatrixToHandler()})
|
||||
|
||||
|
|
@ -1,239 +0,0 @@
|
|||
// Maximum number of histories will be kept
|
||||
const MaxHistory = 10;
|
||||
// History of positive prompt
|
||||
let historyBox = (function () {
|
||||
let _historyBox = [];
|
||||
|
||||
return {
|
||||
push: function (prompt) {
|
||||
if (prompt == _historyBox[_historyBox.length - 1]) return;
|
||||
_historyBox.push(prompt);
|
||||
if (MaxHistory < _historyBox.length) {
|
||||
_historyBox.shift();
|
||||
}
|
||||
},
|
||||
pop: function () {
|
||||
let prePrompt = _historyBox.pop();
|
||||
return prePrompt;
|
||||
},
|
||||
};
|
||||
})();
|
||||
// History of negative prompt
|
||||
let nhistoryBox = (function () {
|
||||
let _historyBox = [];
|
||||
|
||||
return {
|
||||
push: function (prompt) {
|
||||
if (prompt == _historyBox[_historyBox.length - 1]) return;
|
||||
_historyBox.push(prompt);
|
||||
if (MaxHistory < _historyBox.length) {
|
||||
_historyBox.shift();
|
||||
}
|
||||
},
|
||||
pop: function () {
|
||||
let prePrompt = _historyBox.pop();
|
||||
return prePrompt;
|
||||
},
|
||||
};
|
||||
})();
|
||||
// Round function
|
||||
function round(value) {
|
||||
return Math.round(value * 10000) / 10000;
|
||||
}
|
||||
function convert(input) {
|
||||
[111, 2233];
|
||||
const re_attention = /\{|\[|\}|\]|[^\{\}\[\]]+/gmu;
|
||||
let text = input
|
||||
.replace(":", ":")
|
||||
.replace("(", "(")
|
||||
.replace(")", ")")
|
||||
.replace(/\s+/gi, " ")
|
||||
.replace(",", ",")
|
||||
.replace("<", ", <")
|
||||
.replace(", ,", ",")
|
||||
.replace(",,", ",")
|
||||
.replace("> <", ">, <");
|
||||
|
||||
let res = [];
|
||||
|
||||
let curly_brackets = [];
|
||||
let square_brackets = [];
|
||||
|
||||
const curly_bracket_multiplier = 1.05;
|
||||
const square_bracket_multiplier = 1 / 1.05;
|
||||
|
||||
function multiply_range(start_position, multiplier) {
|
||||
for (let pos = start_position; pos < res.length; pos++) {
|
||||
res[pos][1] = round(res[pos][1] * multiplier);
|
||||
}
|
||||
}
|
||||
|
||||
for (const match of text.matchAll(re_attention)) {
|
||||
let word = match[0];
|
||||
|
||||
if (word == "{") {
|
||||
curly_brackets.push(res.length);
|
||||
} else if (word == "[") {
|
||||
square_brackets.push(res.length);
|
||||
} else if (word == "}" && curly_brackets.length > 0) {
|
||||
multiply_range(curly_brackets.pop(), curly_bracket_multiplier);
|
||||
} else if (word == "]" && square_brackets.length > 0) {
|
||||
multiply_range(square_brackets.pop(), square_bracket_multiplier);
|
||||
} else {
|
||||
res.push([word, 1.0]);
|
||||
}
|
||||
}
|
||||
|
||||
for (const pos of curly_brackets) {
|
||||
multiply_range(pos, curly_bracket_multiplier);
|
||||
}
|
||||
|
||||
for (const pos of square_brackets) {
|
||||
multiply_range(pos, square_bracket_multiplier);
|
||||
}
|
||||
|
||||
if (res.length == 0) {
|
||||
res = [["", 1.0]];
|
||||
}
|
||||
|
||||
// console.log(res);
|
||||
// merge runs of identical weights
|
||||
let i = 0;
|
||||
while (i + 1 < res.length) {
|
||||
// console.log("test:" + res[i] + " : " + res[i+1])
|
||||
if (res[i][1] == res[i + 1][1]) {
|
||||
res[i][0] = res[i][0] + res[i + 1][0];
|
||||
// console.log("splicing:" + res[i+1]);
|
||||
res.splice(i + 1, 1);
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
// console.log(res);
|
||||
|
||||
let result = "";
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
if (res[i][1] == 1.0) {
|
||||
result += res[i][0];
|
||||
} else {
|
||||
result += "(" + res[i][0] + ":" + res[i][1].toString() + ")";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function dispatchInputEvent(target) {
|
||||
let inputEvent = new Event("input");
|
||||
Object.defineProperty(inputEvent, "target", { value: target });
|
||||
target.dispatchEvent(inputEvent);
|
||||
}
|
||||
|
||||
function onClickConvert(type) {
|
||||
const default_prompt = "";
|
||||
const default_negative = "";
|
||||
|
||||
let result = "";
|
||||
let prompt = gradioApp().querySelector(`#${type}_prompt > label > textarea`);
|
||||
historyBox.push(prompt.value);
|
||||
result = convert(prompt.value);
|
||||
if (result.length != 0) {
|
||||
if (result.match(/^masterpiece, best quality,/) == null) {
|
||||
result = default_prompt + result;
|
||||
}
|
||||
}
|
||||
prompt.value = result;
|
||||
dispatchInputEvent(prompt);
|
||||
|
||||
result = "";
|
||||
let negprompt = gradioApp().querySelector(
|
||||
`#${type}_neg_prompt > label > textarea`
|
||||
);
|
||||
nhistoryBox.push(negprompt.value);
|
||||
result = convert(negprompt.value);
|
||||
if (result.length != 0) {
|
||||
if (result.match(/^lowres,/) == null) {
|
||||
result = default_negative + result;
|
||||
}
|
||||
} else {
|
||||
result = default_negative;
|
||||
}
|
||||
negprompt.value = result;
|
||||
dispatchInputEvent(negprompt);
|
||||
}
|
||||
|
||||
function onClickGenerate(type) {
|
||||
let prompt = gradioApp().querySelector(`#${type}g_prompt > label > textarea`);
|
||||
historyBox.push(prompt.value);
|
||||
let negprompt = gradioApp().querySelector(
|
||||
`#${type}_neg_prompt > label > textarea`
|
||||
);
|
||||
nhistoryBox.push(negprompt.value);
|
||||
}
|
||||
|
||||
function onClickUndo(type) {
|
||||
let prompt = gradioApp().querySelector(`#${type}_prompt > label > textarea`);
|
||||
let prePrompt = historyBox.pop();
|
||||
|
||||
if (!prePrompt) {
|
||||
prompt.value = "";
|
||||
} else {
|
||||
prompt.value = prePrompt;
|
||||
}
|
||||
dispatchInputEvent(prompt);
|
||||
|
||||
let negprompt = gradioApp().querySelector(
|
||||
`#${type}_neg_prompt > label > textarea`
|
||||
);
|
||||
let prenegprompt = nhistoryBox.pop();
|
||||
|
||||
if (!prenegprompt) {
|
||||
negprompt.value = "";
|
||||
} else {
|
||||
negprompt.value = prenegprompt;
|
||||
}
|
||||
dispatchInputEvent(negprompt);
|
||||
}
|
||||
|
||||
function createButton(id, innerHTML, onClick) {
|
||||
const button = document.createElement("button");
|
||||
button.id = id;
|
||||
button.type = "button";
|
||||
button.innerHTML = innerHTML;
|
||||
button.className = "gr-button gr-button-lg gr-button-secondary";
|
||||
button.style = `padding-left: 0.1em; padding-right: 0em; margin: 0.1em 0;max-height: 2em; max-width: 6em`;
|
||||
button.addEventListener("click", onClick);
|
||||
return button;
|
||||
}
|
||||
|
||||
function addPromptButton(type) {
|
||||
const generateBtn = gradioApp().querySelector(`#${type}_generate`);
|
||||
const actionsColumn = gradioApp().querySelector(`#${type}_actions_column`);
|
||||
const nai2local = gradioApp().querySelector(`#${type}_nai2local`);
|
||||
|
||||
if (!generateBtn || !actionsColumn || nai2local) return;
|
||||
|
||||
generateBtn.addEventListener("click", () => onClickGenerate(type));
|
||||
|
||||
const nai2LocalArea = document.createElement("div");
|
||||
nai2LocalArea.id = `${type}_nai2local`;
|
||||
nai2LocalArea.className = "overflow-hidden flex col gap-4";
|
||||
nai2LocalArea.style =
|
||||
"padding: 0.4em 0em; display: flex; justify-content: center;";
|
||||
|
||||
const convertBtn = createButton("nai2localconvert", "🪄", () =>
|
||||
onClickConvert(type)
|
||||
);
|
||||
const undoBtn = createButton("nai2localUndo", "History", () =>
|
||||
onClickUndo(type)
|
||||
);
|
||||
|
||||
nai2LocalArea.appendChild(convertBtn);
|
||||
nai2LocalArea.appendChild(undoBtn);
|
||||
|
||||
actionsColumn.append(nai2LocalArea);
|
||||
}
|
||||
|
||||
onUiUpdate(() => {
|
||||
addPromptButton("txt2img");
|
||||
addPromptButton("img2img");
|
||||
});
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
class BracketChecker {
|
||||
constructor(textArea, counterElt) {
|
||||
this.textArea = textArea;
|
||||
this.counterElt = counterElt;
|
||||
this.errorStrings = [
|
||||
{
|
||||
regex: /\(/g,
|
||||
error:
|
||||
"(...) - Different number of opening and closing parentheses detected.\n",
|
||||
},
|
||||
{
|
||||
regex: /\[/g,
|
||||
error:
|
||||
"[...] - Different number of opening and closing square brackets detected.\n",
|
||||
},
|
||||
{
|
||||
regex: /\{/g,
|
||||
error:
|
||||
"{...} - Different number of opening and closing curly brackets detected.\n",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
check() {
|
||||
var title = "";
|
||||
this.errorStrings.forEach(({ regex, error }) => {
|
||||
var openMatches = (this.textArea.value.match(regex) || []).length;
|
||||
var closeMatches = (
|
||||
this.textArea.value.match(
|
||||
regex.replace(/\(/g, ")").replace(/\[/g, "]").replace(/\{/g, "}")
|
||||
) || []
|
||||
).length;
|
||||
if (openMatches != closeMatches) {
|
||||
if (!this.counterElt.title.includes(error)) {
|
||||
title += error;
|
||||
}
|
||||
} else {
|
||||
title = this.counterElt.title.replace(error, "");
|
||||
}
|
||||
});
|
||||
this.counterElt.title = title;
|
||||
this.counterElt.classList.toggle("error", !!title);
|
||||
}
|
||||
}
|
||||
|
||||
function setupBracketChecking(id_prompt, id_counter) {
|
||||
var textarea = gradioApp().querySelector(`#${id_prompt} > label > textarea`);
|
||||
var counter = gradioApp().getElementById(id_counter);
|
||||
var bracketChecker = new BracketChecker(textarea, counter);
|
||||
textarea.addEventListener("input", () => bracketChecker.check());
|
||||
}
|
||||
|
||||
const shadowRootLoaded = setInterval(() => {
|
||||
var shadowRoot = document.querySelector("gradio-app").shadowRoot;
|
||||
if (!shadowRoot) return;
|
||||
var shadowTextArea = shadowRoot.querySelector(
|
||||
`#txt2img_prompt > label > textarea`
|
||||
);
|
||||
if (!shadowTextArea) return;
|
||||
clearInterval(shadowRootLoaded);
|
||||
["txt2img", "txt2img_neg", "img2img", "img2img_neg"].forEach((prompt) => {
|
||||
setupBracketChecking(`${prompt}_prompt`, `${prompt}_token_counter`);
|
||||
setupBracketChecking(
|
||||
`${prompt}_prompt`,
|
||||
`${prompt}_negative_token_counter`
|
||||
);
|
||||
});
|
||||
}, 1000);
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
function quickcssFormatRule(val, ele, colorsSize){
|
||||
//async is not needed, just trying to debug some error from colorpicker
|
||||
ele = parseInt(ele)
|
||||
//get sheet from style tag
|
||||
let quickcssSheet = document.documentElement.querySelector("gradio-app").shadowRoot.querySelector("style").sheet
|
||||
//get it's rules
|
||||
let quickcssCssr = quickcssSheet.cssRules
|
||||
//convert to array for finding index
|
||||
let quickcssCssrArray = Array.from(quickcssCssr)
|
||||
//use custom target to find index
|
||||
let quickcssTarget = quickcssCssrArray.find( item => item.cssText.includes("quickcss_target"))
|
||||
let quickcssTargetIndex = quickcssCssrArray.indexOf(quickcssTarget)
|
||||
//Pull rule out
|
||||
let quickcssRuleAsString = quickcssCssr[quickcssTargetIndex].cssText.toString()
|
||||
//splitter for rule targets and body
|
||||
let ruleSplitIndex = quickcssRuleAsString.indexOf("{")
|
||||
//Target of rule
|
||||
let ruleTargets = quickcssRuleAsString.slice(0, ruleSplitIndex)
|
||||
//Body of rule
|
||||
let quickcssRuleBody = quickcssRuleAsString.slice(ruleSplitIndex)
|
||||
//Rule body edit
|
||||
let asSplit = quickcssRuleBody.split(";")
|
||||
let endStr = asSplit.slice(parseInt(colorsSize)).join(";")
|
||||
//Edit to element position, index and length given as string via hiddenvals components
|
||||
while (asSplit.length > parseInt(colorsSize))
|
||||
{
|
||||
asSplit.pop()
|
||||
}
|
||||
let asArray = new Array
|
||||
asSplit.forEach( e => {asArray.push(e.split(":"))})
|
||||
let stringarray = new Array
|
||||
asArray.forEach( (e, i) => {stringarray.push( i==ele ? `${e[0]}: ${val}`: `${e[0]}: ${e[1]}`)})
|
||||
stringarray = stringarray.join(";") + `;${endStr}`
|
||||
let cssRule = ruleTargets + stringarray
|
||||
//Delete old rule at
|
||||
quickcssSheet.deleteRule(quickcssTargetIndex)
|
||||
//insert (as in add at same location)
|
||||
quickcssSheet.insertRule(cssRule, quickcssTargetIndex)
|
||||
//returns must equal inputs size, so outputs must matchsize, python fn hijacks for finishing save data
|
||||
return [stringarray, "", ""]
|
||||
}
|
||||
|
||||
//Register js fx's
|
||||
//they must support a destroy method
|
||||
|
||||
qkcssFXMap = {};
|
||||
|
||||
function launchEffect(filename){
|
||||
qkcssFXMap[filename][0]()
|
||||
}
|
||||
|
||||
function destroyEffect(filename){
|
||||
qkcssFXMap[filename][1].destroy()
|
||||
}
|
||||
|
||||
//Register js image injectors
|
||||
qkcssImagemap = {};
|
||||
|
||||
function launchImage(name){
|
||||
qkcssImagemap[name].register()
|
||||
}
|
||||
function removeImage(name){
|
||||
qkcssImagemap[name].destroy()
|
||||
}
|
||||
function updateImage(name, new_name){
|
||||
//notimplemented hidden component to send name?
|
||||
qkcssImagemap[name].updateImage(new_name)
|
||||
}
|
||||
async function refreshImage(name){
|
||||
await qkcssImagemap[name].refreshImage()
|
||||
return name
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "sd-web-ui-kitchen-theme",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"author": "canisminor1990 <i@canisminor.cc>",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "gulp watch",
|
||||
"build": "gulp less"
|
||||
},
|
||||
"dependencies": {
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-less": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^2.8.7"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,387 +0,0 @@
|
|||
import gradio as gr
|
||||
import modules.scripts as scripts
|
||||
from modules import script_callbacks, shared
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
basedir = scripts.basedir()
|
||||
|
||||
|
||||
class MyTab():
|
||||
|
||||
def __init__(self, basedir):
|
||||
#This extensions directory
|
||||
self.extensiondir = basedir
|
||||
#Up two directories, webui root
|
||||
self.webui_dir = Path(self.extensiondir).parents[1]
|
||||
|
||||
|
||||
self.style_folder = os.path.join(basedir, "style_choices")
|
||||
self.backgrounds_folder = os.path.join(self.extensiondir, "backgrounds")
|
||||
self.logos_folder = os.path.join(self.extensiondir, "logos")
|
||||
self.favicon_folder = os.path.join(self.extensiondir, "favicons")
|
||||
self.effects_folder = os.path.join(self.extensiondir, "effects")
|
||||
self.javascript_folder = os.path.join(self.extensiondir, "javascript")
|
||||
self.static_folder = os.path.join(self.webui_dir, "static")
|
||||
|
||||
self.favicon_workaround = gr.HTML(value='<div class="icon-container"></div>', render=False)
|
||||
|
||||
|
||||
self.styles_list = self.get_files(self.style_folder)
|
||||
self.backgrounds_list = self.get_files(self.backgrounds_folder)
|
||||
self.logos_list = self.get_files(self.logos_folder)
|
||||
self.favicon_list = self.get_files(self.favicon_folder)
|
||||
self.effects_list = self.get_files(self.javascript_folder, file_filter=["quickcss.js", "utility.js", "background.js"], split=True)
|
||||
|
||||
|
||||
self.styles_dropdown = gr.Dropdown(label="Styles", render=False, interactive=True, choices=self.styles_list, type="value")
|
||||
self.background_dropdown = gr.Dropdown(label="Background", render=False, interactive=True, choices=self.backgrounds_list, type="value")
|
||||
self.logos_dropdown = gr.Dropdown(label="Logos", render=False, interactive=True, choices=self.logos_list, type="value")
|
||||
self.favicon_dropdown = gr.Dropdown(label="Favicon", render=False, interactive=True, choices=self.favicon_list, type="value")
|
||||
self.effects_dropdown = gr.Dropdown(label="Effects (on until refresh)", render=False, interactive=True, choices=self.effects_list, type="value")
|
||||
|
||||
|
||||
self.apply_style_bttn = gr.Button(value="Apply Style", render=False)
|
||||
self.apply_background_bttn = gr.Button(value="Apply (Reload UI)", render=False)
|
||||
#TODO: background off button to swap image in folder to blankbackground and disable style rule
|
||||
self.refresh_bkcgrnd_droplist_button = gr.Button(value="Refresh List", render=False)
|
||||
self.apply_logo_bttn = gr.Button(value="Apply Logo", render=False)
|
||||
self.apply_favicon_bttn = gr.Button(value="Apply Favicon (edit webui.py to see)", render=False)
|
||||
self.effects_button = gr.Button(value="Activate Selected Script", render=False)
|
||||
self.effects_off_button = gr.Button(value="Deactivate Selected Script", render=False)
|
||||
|
||||
|
||||
self.logo_image = gr.Image(render=False)
|
||||
self.favicon_image = gr.Image(render=False)
|
||||
|
||||
|
||||
self.import_style_file = gr.File(render=False, label="Import CSS file")
|
||||
self.import_background_file = gr.File(render=False, label="Import Background Images")
|
||||
self.import_logo_file = gr.File(render=False, label="Import Logo's (png)")
|
||||
self.import_favicon_file = gr.File(render=False, label="Import favicons (svg)")
|
||||
|
||||
|
||||
self.restart_bttn = gr.Button(value="Apply changes (Reload UI)", render=False, variant="primary")
|
||||
|
||||
self.remove_style = gr.Button(value="Remove Stylesheet", render=False)
|
||||
|
||||
|
||||
# BEGIN CSS COLORPICK COMPONENTS
|
||||
self.save_as_filename = gr.Text(label="Save Name", visible=False, render=False)
|
||||
self.save_button = gr.Button(value="Save", visible=False, render=False, variant="primary")
|
||||
|
||||
#Test for file being set
|
||||
self.file_exists = False
|
||||
self.style_path = os.path.join(self.extensiondir, "style.css")
|
||||
self.start_position_for_save = 0
|
||||
self.insert_colorpicker_break_rule_for_save = 0
|
||||
self.insert_break_rule_for_save = 0
|
||||
if os.path.exists(self.style_path):
|
||||
self.file_exists = True #Conditional for creating inputs
|
||||
self.lines = []
|
||||
line = ""
|
||||
self.dynamic_compatible = False
|
||||
with open(self.style_path, 'r', encoding='utf-8') as cssfile:
|
||||
try:
|
||||
for i, line in enumerate(cssfile):
|
||||
line = line.strip()
|
||||
if "/*BREAKFILEREADER*/" in line:
|
||||
self.insert_break_rule_for_save = i - self.start_position_for_save
|
||||
break
|
||||
elif "/*ENDCOLORPICKERS*/" in line:
|
||||
self.insert_colorpicker_break_rule_for_save = i - self.start_position_for_save
|
||||
continue
|
||||
if "quickcss_target" in line:
|
||||
self.dynamic_compatible = True
|
||||
self.start_position_for_save = i+1
|
||||
continue
|
||||
if self.dynamic_compatible:
|
||||
if len(line) > 0:
|
||||
self.lines.append(line.split(":"))
|
||||
except UnicodeDecodeError as error:
|
||||
print(f"{error}\nCheck style.css in this extensions folder.")
|
||||
|
||||
|
||||
if self.dynamic_compatible:
|
||||
self.dynamically_generated_components = [gr.ColorPicker(label=x[0].replace("-", "").replace("_", " ").title(), render=False, elem_id="quikcss_colorpicker", value=x[1].replace(";", "").strip())
|
||||
if i < self.insert_colorpicker_break_rule_for_save else
|
||||
gr.Slider(minimum=0, maximum=100, step=1, label=x[0].replace("-", "").replace("_", " ").title(), render=False, elem_id="quikcss_slider", value=x[1].replace(";", "").strip())
|
||||
for i,x in enumerate(self.lines)
|
||||
]
|
||||
else:
|
||||
self.dynamically_generated_components = []
|
||||
|
||||
# hidden_vals acts like an index, holds int values that are used in js
|
||||
self.hidden_vals = [gr.Text(value=str(x), render=False, visible=False) for x in range(len(self.dynamically_generated_components))]
|
||||
|
||||
# length_of_colors similar to hidden vals, but provides length so js knows the limit when parsing rules
|
||||
self.length_of_colors = gr.Text(value=len(self.dynamically_generated_components), visible=False, render=False)
|
||||
|
||||
# used as padding so we don't list index error or http 500 internal server, or http 422 forEach can't over undefined (promise pending)
|
||||
self.dummy_picker = gr.Text(visible=False, render=False, elem_id="hidden")
|
||||
|
||||
# Acts like catcher, actual values store in list
|
||||
self.js_result_component = gr.Text(render=False, interactive=False)
|
||||
|
||||
#dummy component for general purpose, currently used for _js effects; holds no relevant data, just for input/output element quota
|
||||
self._dummy = gr.Text(value="", visible=False, render=False, show_label=False, interactive=False)
|
||||
|
||||
def ui(self, *args, **kwargs):
|
||||
with gr.Blocks(analytics_enabled=False) as ui:
|
||||
self.favicon_workaround.render()
|
||||
with gr.Accordion(label="Some instructions", open=False):
|
||||
gr.Markdown(value="""<center>This is a mix from old style to new style. It is not in it's finished state</center>
|
||||
<center>To see effects, you must use dropdown, select as sheet, click apply, click restart. More options will be available on restart</center>
|
||||
<center>I know it lives as a tab, but this was meant to be a demo at first, now it's growing to something more</center>
|
||||
|
||||
<center>To see favicon take affect, you will need to add `favicon_path="favicon.svg"` to webui.py</center>
|
||||
<center>To do this, open file, search for `prevent_thread_lock` add comma, paste in text, save.</center>
|
||||
|
||||
<center>You may need to undo this for an update, if you have git issues and don't know how to deal with them</center>
|
||||
<center>This won't break your system, if you find you can't update, try `git checkout webui.py` ~~`git fetch --all` `git reset --hard origin/master`~~</center>
|
||||
|
||||
<center>Once again, this `dynamic` demo has not removed/re-implemented all features present</center>
|
||||
""")
|
||||
if self.file_exists and self.dynamic_compatible:
|
||||
with gr.Row(equal_height=True):
|
||||
self.save_as_filename.render()
|
||||
self.save_button.render()
|
||||
#Necessary for values being accessible
|
||||
self.length_of_colors.render()
|
||||
self.dummy_picker.render()
|
||||
self.js_result_component.render()
|
||||
#Render hidden vals that serve as indices to map
|
||||
for h in self.hidden_vals:
|
||||
h.render()
|
||||
with gr.Row():
|
||||
#Render adjusters
|
||||
for c in self.dynamically_generated_components:
|
||||
with gr.Column(elem_id="quickcss_colorpicker"):
|
||||
c.render()
|
||||
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
self.styles_dropdown.render()
|
||||
self.apply_style_bttn.render()
|
||||
with gr.Column():
|
||||
self.background_dropdown.render()
|
||||
with gr.Row():
|
||||
self.apply_background_bttn.render()
|
||||
self.refresh_bkcgrnd_droplist_button.render()
|
||||
with gr.Column():
|
||||
self.logos_dropdown.render()
|
||||
self.apply_logo_bttn.render()
|
||||
with gr.Column():
|
||||
self.favicon_dropdown.render()
|
||||
self.apply_favicon_bttn.render()
|
||||
with gr.Column():
|
||||
self.effects_dropdown.render()
|
||||
with gr.Row():
|
||||
self.effects_button.render()
|
||||
self.effects_off_button.render()
|
||||
|
||||
with gr.Accordion(label="Import Files", open=False):
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
self.import_style_file.render()
|
||||
with gr.Column():
|
||||
self.import_background_file.render()
|
||||
with gr.Column():
|
||||
self.import_logo_file.render()
|
||||
with gr.Column():
|
||||
self.import_favicon_file.render()
|
||||
|
||||
with gr.Row():
|
||||
self.restart_bttn.render()
|
||||
self.remove_style.render()
|
||||
|
||||
with gr.Row():
|
||||
self.logo_image.render()
|
||||
self.favicon_image.render()
|
||||
self._dummy.render()
|
||||
|
||||
# Handlers
|
||||
#Generate colorpickers and sliders handlers
|
||||
if self.file_exists:
|
||||
for comp,val in zip(self.dynamically_generated_components, self.hidden_vals):
|
||||
comp.change(
|
||||
fn = lambda *x: self.process_for_save(*x),
|
||||
_js = "quickcssFormatRule",
|
||||
inputs = [comp, val, self.length_of_colors],
|
||||
outputs = [self.js_result_component] + [self.save_as_filename, self.dummy_picker]
|
||||
)
|
||||
self.save_as_filename.change(
|
||||
fn = lambda x: gr.update(visible=bool(x)),
|
||||
inputs = self.save_as_filename,
|
||||
outputs = self.save_button
|
||||
)
|
||||
self.save_button.click(
|
||||
fn = self.save,
|
||||
inputs = [self.js_result_component, self.save_as_filename],
|
||||
outputs = [self.js_result_component, self.styles_dropdown]
|
||||
)
|
||||
|
||||
#Handler cont.
|
||||
#Common interface
|
||||
#NOTE: These dropdowns affect image placeholders
|
||||
self.logos_dropdown.change(
|
||||
fn = lambda x: self.get_image(x, folder = "logos"),
|
||||
inputs = self.logos_dropdown,
|
||||
outputs = self.logo_image
|
||||
)
|
||||
|
||||
self.favicon_dropdown.change(
|
||||
fn = lambda x: self.get_image(x, folder = "favicons"),
|
||||
inputs = self.favicon_dropdown,
|
||||
outputs = self.favicon_image
|
||||
)
|
||||
|
||||
#buttons
|
||||
self.apply_style_bttn.click(
|
||||
fn = self.apply_choice_wrapper(self.style_folder, self.extensiondir, "style.css"),
|
||||
inputs = self.styles_dropdown
|
||||
)
|
||||
|
||||
self.apply_background_bttn.click(
|
||||
fn = self.apply_choice_wrapper(self.backgrounds_folder, self.static_folder, "background.png"),#TODO: MAYBE: delete file extension
|
||||
_js = "injectBackground.refreshImage",
|
||||
inputs = self.background_dropdown,
|
||||
outputs=self._dummy
|
||||
)
|
||||
|
||||
self.refresh_bkcgrnd_droplist_button.click(
|
||||
fn = lambda: self.refresh_list(self.refresh_bkcgrnd_droplist_button, self.backgrounds_folder, self.background_dropdown),
|
||||
outputs=self.background_dropdown
|
||||
)
|
||||
|
||||
self.apply_logo_bttn.click(
|
||||
fn = self.apply_choice_wrapper(self.logos_folder, self.static_folder, "logo.png"),#TODO Update css files and change dir to static
|
||||
inputs = self.logos_dropdown,
|
||||
)
|
||||
|
||||
self.apply_favicon_bttn.click(
|
||||
fn = self.apply_choice_wrapper(self.favicon_folder, self.static_folder, "favicon.svg"),#TODO update css files and change dir to static
|
||||
inputs = self.favicon_dropdown
|
||||
)
|
||||
|
||||
self.effects_button.click(
|
||||
fn = None,
|
||||
_js = "launchEffect",
|
||||
inputs = self.effects_dropdown,
|
||||
outputs = self._dummy
|
||||
)
|
||||
|
||||
self.effects_off_button.click(
|
||||
fn = None,
|
||||
_js = "destroyEffect",
|
||||
inputs = self.effects_dropdown,
|
||||
outputs = self._dummy
|
||||
)
|
||||
|
||||
self.remove_style.click(
|
||||
fn = lambda: self.delete_style()
|
||||
)
|
||||
|
||||
self.restart_bttn.click(fn=self.local_request_restart, _js='restart_reload', inputs=[], outputs=[])
|
||||
|
||||
#File Importers
|
||||
self.import_style_file.change(
|
||||
fn = lambda tmp_file: self.import_file_from_path(tmp_file, target_folder="style_choices", comp = self.styles_dropdown, func = self.get_files, folder=self.style_folder, focus_list=self.styles_list),
|
||||
inputs=self.import_style_file,
|
||||
outputs=self.styles_dropdown
|
||||
)
|
||||
|
||||
self.import_background_file.change(
|
||||
fn = lambda tmp_file: self.import_file_from_path(tmp_file, target_folder="backgrounds", comp = self.background_dropdown, func = self.get_files, folder=self.backgrounds_folder, focus_list=self.backgrounds_list),
|
||||
inputs=self.import_background_file,
|
||||
outputs=self.background_dropdown
|
||||
)
|
||||
|
||||
self.import_logo_file.change(
|
||||
fn = lambda tmp_file: self.import_file_from_path(tmp_file, target_folder="logos", comp = self.logos_dropdown, func = self.get_files, folder=self.logos_folder, focus_list=self.logos_list),
|
||||
inputs=self.import_logo_file,
|
||||
outputs=self.logos_dropdown
|
||||
)
|
||||
|
||||
|
||||
self.import_favicon_file.change(
|
||||
fn = lambda tmp_file: self.import_file_from_path(tmp_file, target_folder="favicons", comp = self.favicon_dropdown, func = self.get_files, folder=self.favicon_folder, focus_list=self.favicon_list),
|
||||
inputs=self.import_favicon_file,
|
||||
outputs=self.favicon_dropdown
|
||||
)
|
||||
|
||||
|
||||
return [(ui, "Theme", "theme")]
|
||||
|
||||
|
||||
def import_file_from_path(self, tmp_file_obj, target_folder, comp, func, **kwargs):
|
||||
if tmp_file_obj:
|
||||
shutil.copy(tmp_file_obj.name, os.path.join(self.extensiondir, target_folder, tmp_file_obj.orig_name))
|
||||
# Update appropriate list
|
||||
# Make backend the same as front-end so it matches when selected
|
||||
comp.choices = func(**kwargs)
|
||||
tmp_file_obj.flush()
|
||||
# return sends update to front-end
|
||||
return gr.update(choices=comp.choices)
|
||||
|
||||
|
||||
def get_files(self, folder, focus_list=[], file_filter=[], split=False):
|
||||
focus_list = [file_name if not split else os.path.splitext(file_name)[0] for file_name in os.listdir(folder) if os.path.isfile(os.path.join(folder, file_name)) and file_name not in file_filter]
|
||||
return focus_list
|
||||
|
||||
|
||||
def apply_choice_wrapper(self, src_base_path, dst_base_path, name):
|
||||
"""Encapsulation so I don't need a different function for each type"""
|
||||
def apply_choice(selection):
|
||||
shutil.copy(os.path.join(src_base_path, selection), os.path.join(dst_base_path, name))
|
||||
return apply_choice
|
||||
|
||||
|
||||
def get_image(self, name, folder):
|
||||
return os.path.join(self.extensiondir, folder, name)
|
||||
|
||||
|
||||
def refresh_list(self, component, folder, focus_list, file_filter=[]):
|
||||
component.choices = self.get_files(folder, focus_list, file_filter)
|
||||
return gr.update(choices=component.choices)
|
||||
|
||||
|
||||
|
||||
def delete_style(self):
|
||||
try:
|
||||
os.remove(os.path.join(self.extensiondir, "style.css"))
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
|
||||
def local_request_restart(self):
|
||||
"Restart button"
|
||||
shared.state.interrupt()
|
||||
shared.state.need_restart = True
|
||||
|
||||
|
||||
def process_for_save(self, x, *y):
|
||||
return [x] + [gr.update(visible=True), None]
|
||||
|
||||
|
||||
def save(self, js_cmp_val, filename):
|
||||
rules = [f" {e};\n" for e in js_cmp_val[1:-1].split(";")][:-1]
|
||||
#issue, save button needs to stay hidden until some color change
|
||||
rules.insert(self.insert_colorpicker_break_rule_for_save, " /*ENDCOLORPICKERS*/\n")
|
||||
rules.insert(self.insert_break_rule_for_save, " /*BREAKFILEREADER*/\n")
|
||||
with open(self.style_path, 'r+') as file:
|
||||
lines = file.readlines()
|
||||
start_pos = self.start_position_for_save
|
||||
for i, rule in enumerate(rules):
|
||||
lines[start_pos + i] = rule
|
||||
file.seek(0)
|
||||
file.writelines(lines)
|
||||
self.styles_dropdown.choices.insert(0, f"{filename}.css")
|
||||
shutil.copy(self.style_path, os.path.join(self.style_folder, f"{filename}.css"))
|
||||
return ["Saved", gr.update(choices=self.styles_dropdown.choices, value=self.styles_dropdown.choices[0])]
|
||||
|
||||
|
||||
|
||||
tab = MyTab(basedir)
|
||||
script_callbacks.on_ui_tabs(tab.ui)
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
from dataclasses import dataclass
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
from modules import scripts
|
||||
|
||||
@dataclass
|
||||
class DefaultFile:
|
||||
"""Move file to location as filename"""
|
||||
og_file:str
|
||||
current_path:str
|
||||
dir:str
|
||||
save_as_filename:str
|
||||
|
||||
|
||||
#class UpdateInstructions:
|
||||
# @staticmethod
|
||||
# def instructions(other_clss):
|
||||
# #Create new folder
|
||||
# in_root_folders = ["static"]
|
||||
# #in_extension_folder = []
|
||||
# for f_name in in_root_folders:
|
||||
# other_clss.check_folder
|
||||
|
||||
|
||||
class BasicUpdater:
|
||||
|
||||
def __init__(self):
|
||||
#sd-web-ui-qkcss dir
|
||||
self.extensions_dir = scripts.basedir()
|
||||
|
||||
self.root_dir = Path(self.extensions_dir).parents[1]
|
||||
self.static_dir = os.path.join(self.root_dir, "static")
|
||||
|
||||
self.style_folder = os.path.join(self.extensions_dir, "style_choices")
|
||||
self.logos_folder = os.path.join(self.extensions_dir, "logos")
|
||||
self.favicon_folder = os.path.join(self.extensions_dir, "favicons")
|
||||
self.backgrounds_folder = os.path.join(self.extensions_dir, "backgrounds")
|
||||
self.effects_folder = os.path.join(self.extensions_dir, "effects")
|
||||
self.javascript_folder = os.path.join(self.extensions_dir, "javascript")
|
||||
|
||||
self.file_defaults = [
|
||||
DefaultFile(og_file="logo.png", current_path=self.logos_folder, dir=self.static_dir, save_as_filename="logo.png"),
|
||||
DefaultFile(r"favicon Original.svg", self.favicon_folder, self.static_dir, "favicon.svg"),
|
||||
DefaultFile("blankbackground.png", self.backgrounds_folder, self.static_dir, "background.png")
|
||||
]
|
||||
|
||||
self.updater_file = os.path.join(self.extensions_dir, "update")
|
||||
if os.path.exists(self.updater_file):
|
||||
self.check_folders(self.static_dir)
|
||||
for fd in self.file_defaults:
|
||||
self.clone_file(fd)
|
||||
#UpdateInstructions.instructions(self)
|
||||
os.remove(self.updater_file)
|
||||
|
||||
|
||||
def check_folders(self, folder_path):
|
||||
if not os.path.exists(folder_path):
|
||||
os.mkdir(folder_path)
|
||||
|
||||
def clone_file(self, defaults_object:DefaultFile):
|
||||
from_file = os.path.join(defaults_object.current_path, defaults_object.og_file)
|
||||
to_file = os.path.join(defaults_object.dir, defaults_object.save_as_filename)
|
||||
if not os.path.exists(to_file):
|
||||
shutil.copy(from_file, to_file)
|
||||
|
||||
BasicUpdater()
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
.extra-network-thumbs {
|
||||
|
||||
|
||||
|
||||
.actions {
|
||||
.name {
|
||||
background:linear-gradient(0deg, rgba(0,0,0,.8), transparent);
|
||||
font-weight: 500;
|
||||
text-shadow: 0 1px 1px rgba(0,0,0,.9);
|
||||
}
|
||||
.additional > ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(180deg, rgba(0,0,0,.8), transparent) !important;
|
||||
opacity: 0;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: var(--borderRadiusXS);
|
||||
background-size: cover;
|
||||
box-shadow: var(--boxShadow);
|
||||
outline: 1px solid rgba(0,0,0,.5);
|
||||
transition: all 0.2s ease-in-out;
|
||||
&:hover {
|
||||
transform: scale(1.5);
|
||||
z-index: 500;
|
||||
box-shadow: 0 6px 24px -4px rgba(0,0,0,.8);
|
||||
}
|
||||
}
|
||||
|
||||
.metadata-button {
|
||||
font-size: 10px !important;
|
||||
right: 4px;
|
||||
top: 24px;
|
||||
opacity: 0;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
.livePreview,
|
||||
.gradio-gallery,
|
||||
.gradio-image,
|
||||
.gradio-video,
|
||||
.gradio-file{
|
||||
background: var(--galleryBackground) !important;
|
||||
border: 2px solid var(--colorBorder) !important;
|
||||
border-radius: var(--block-radius) !important;
|
||||
}
|
||||
|
||||
|
||||
div.svelte-awbtu4 {
|
||||
.livePreview,
|
||||
.gradio-gallery,
|
||||
.gradio-image,
|
||||
.gradio-video,
|
||||
.gradio-file{
|
||||
background: var(--galleryBackground) !important;
|
||||
border: 2px solid var(--colorBorder) !important;
|
||||
border-radius: var(--block-radius) !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
#quicksettings {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
flex-wrap: nowrap;
|
||||
top: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&:before {
|
||||
content: "";
|
||||
display: block;
|
||||
background: var(--logo) no-repeat;
|
||||
width: 129px;
|
||||
height: 26px;
|
||||
z-index: 1000;
|
||||
margin-right: 36px;
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
height: 121px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
border-block-end: 1px solid var(--colorBorderSecondary);
|
||||
background: var(--colorFillQuaternary);
|
||||
backdrop-filter: blur(24px);
|
||||
}
|
||||
> * {
|
||||
z-index: 1000;
|
||||
}
|
||||
button.svelte-1ipelgc {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
#tabs {
|
||||
> .tabitem {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: var(--padding);
|
||||
margin-top: 118px;
|
||||
}
|
||||
|
||||
> div:first-child {
|
||||
position: fixed;
|
||||
top: 90px;
|
||||
z-index: 1000;
|
||||
flex-wrap: nowrap;
|
||||
width: 100%;
|
||||
border: none;
|
||||
|
||||
> button {
|
||||
border: none;
|
||||
border-bottom: 2px solid transparent !important;
|
||||
flex: none;
|
||||
&:hover {
|
||||
border: none;
|
||||
border-bottom: 2px solid var(--colorPrimary) !important;
|
||||
flex: none;
|
||||
}
|
||||
&.selected {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 2px solid var(--colorPrimary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
[id$="2img_prompt"] textarea {
|
||||
color: rgba(208, 226, 178, 0.98) !important;
|
||||
max-height: 84px;
|
||||
overflow-y: auto;
|
||||
&:focus {
|
||||
color: rgba(244, 255, 225, 0.98) !important;
|
||||
}
|
||||
}
|
||||
|
||||
[id$="2img_neg_prompt"] textarea {
|
||||
color: rgba(236, 210, 213, 0.98) !important;
|
||||
max-height: 84px;
|
||||
overflow-y: auto;
|
||||
&:focus {
|
||||
color: rgba(255, 240, 242, 0.98) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.block.token-counter span {
|
||||
backdrop-filter: blur(24px);
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
.block.svelte-mppz8v {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
[id$="_script_container"] {
|
||||
margin-top: 24px;
|
||||
|
||||
.block.svelte-mppz8v {
|
||||
border: unset !important;
|
||||
}
|
||||
|
||||
> div:not(.absolute) {
|
||||
background-color: var(--colorFillTertiary) !important;
|
||||
border-color: transparent !important;
|
||||
transition: all 0.3s ease-in-out !important;
|
||||
margin-bottom: var(--marginSM) !important;
|
||||
margin-top: 0 !important;
|
||||
padding: var(--padding) !important;
|
||||
border-radius: var(--borderRadius) !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
input[type="range"] {
|
||||
-webkit-appearance: none !important ;
|
||||
background: transparent !important;
|
||||
|
||||
&:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
&::-webkit-slider-runnable-track {
|
||||
cursor: pointer !important;
|
||||
height: 6px !important;
|
||||
border-radius: 3px !important;
|
||||
background: var(--colorFill) !important;
|
||||
opacity: 0.6 !important;
|
||||
}
|
||||
|
||||
&:hover::-webkit-slider-runnable-track {
|
||||
background: var(--colorPrimary) !important;
|
||||
opacity: 1 !important;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
&::-moz-range-track {
|
||||
cursor: pointer !important;
|
||||
height: 6px !important;
|
||||
border-radius: 3px !important;
|
||||
background: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
&:hover::-moz-range-track {
|
||||
background: var(--colorPrimary) !important;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
&::-ms-fill-upper,
|
||||
&::-ms-fill-lower {
|
||||
cursor: pointer !important;
|
||||
height: 6px !important;
|
||||
border-radius: 3px !important;
|
||||
background: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
&:hover::-ms-fill-upper,
|
||||
&:hover::-ms-fill-lower {
|
||||
background: var(--colorBgElevated) !important;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
border: 2px solid var(--colorText) !important;
|
||||
height: 16px !important;
|
||||
width: 16px !important;
|
||||
border-radius: 16px !important;
|
||||
background: var(--colorBgElevated) !important;
|
||||
cursor: pointer !important;
|
||||
-webkit-appearance: none !important;
|
||||
margin-top: -5px !important;
|
||||
}
|
||||
|
||||
&:active::-webkit-slider-thumb {
|
||||
box-shadow: 0 0 3px var(--colorPrimary) !important;
|
||||
border: 2px solid var(--colorPrimary) !important;
|
||||
background: var(--colorBgElevated) !important;
|
||||
}
|
||||
|
||||
&::-moz-range-thumb {
|
||||
border: 2px solid var(--colorText) !important;
|
||||
height: 16px !important;
|
||||
width: 16px !important;
|
||||
border-radius: 16px !important;
|
||||
background: var(--colorBgElevated) !important;
|
||||
cursor: pointer !important;
|
||||
margin-top: -5px !important;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
&:active::-moz-range-thumb {
|
||||
box-shadow: 0 0 3px var(--colorPrimary) !important;
|
||||
border: 2px solid var(--colorPrimary) !important;
|
||||
background: var(--colorBgElevated) !important;
|
||||
}
|
||||
|
||||
&::-ms-thumb {
|
||||
border: 2px solid var(--colorText) !important;
|
||||
height: 16px !important;
|
||||
width: 16px !important;
|
||||
border-radius: 16px !important;
|
||||
background: var(--colorBgElevated) !important;
|
||||
cursor: pointer !important;
|
||||
margin-top: -5px !important;
|
||||
}
|
||||
|
||||
&:active::-ms-thumb {
|
||||
box-shadow: 0 0 3px var(--colorPrimary) !important;
|
||||
border: 2px solid var(--colorPrimary) !important;
|
||||
background: var(--colorBgElevated) !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
[id$="_row_aspect_ratio"],
|
||||
[id$="_row_resolutions"] {
|
||||
display: inline-block !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 180px !important;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* Root */
|
||||
@import "utils/normalize";
|
||||
|
||||
/* Var */
|
||||
@import "var/antd";
|
||||
@import "var/gradioRoot";
|
||||
@import "var/gradioDark";
|
||||
|
||||
/* Components */
|
||||
@import "components/header";
|
||||
@import "components/sliders";
|
||||
@import "components/prompt-textarea";
|
||||
@import "components/gallery";
|
||||
@import "components/script-container";
|
||||
@import "components/extra-network";
|
||||
|
||||
/* Plugin */
|
||||
@import "plugin/aspect_ratio";
|
||||
|
||||
/* Theme Fix*/
|
||||
.gradio-container {
|
||||
font-size: var(--fontSize);
|
||||
margin: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
background-image: radial-gradient(
|
||||
circle 600px at calc(100% - 300px) 300px,
|
||||
var(--colorPrimaryBgHover),
|
||||
var(--colorBgLayout)
|
||||
);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
||||
#txtimg_hr_finalres {
|
||||
color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
#interrogate, #deepbooru {
|
||||
max-height: 72px;;
|
||||
}
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the `main` element consistently in IE.
|
||||
*/
|
||||
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
:root {
|
||||
--colorPrimaryBg: #111a2c;
|
||||
--colorPrimaryBgHover: #112545;
|
||||
--colorPrimaryBorder: #15325b;
|
||||
--colorPrimaryBorderHover: #15417e;
|
||||
--colorPrimaryHover: #3c89e8;
|
||||
--colorPrimary: #1668dc;
|
||||
--colorPrimaryActive: #1554ad;
|
||||
--colorPrimaryTextHover: #3c89e8;
|
||||
--colorPrimaryText: #1668dc;
|
||||
--colorPrimaryTextActive: #1554ad;
|
||||
--colorErrorBg: #2c1618;
|
||||
--colorErrorBgHover: #451d1f;
|
||||
--colorErrorBorder: #5b2526;
|
||||
--colorErrorBorderHover: #7e2e2f;
|
||||
--colorErrorHover: #e86e6b;
|
||||
--colorError: #dc4446;
|
||||
--colorErrorActive: #ad393a;
|
||||
--colorErrorTextHover: #e86e6b;
|
||||
--colorErrorText: #dc4446;
|
||||
--colorErrorTextActive: #ad393a;
|
||||
--colorText: rgba(255, 255, 255, 0.85);
|
||||
--colorTextSecondary: rgba(255, 255, 255, 0.65);
|
||||
--colorTextTertiary: rgba(255, 255, 255, 0.45);
|
||||
--colorTextQuaternary: rgba(255, 255, 255, 0.25);
|
||||
--colorBgContainer: #141414;
|
||||
--colorBgElevated: #1f1f1f;
|
||||
--colorBgLayout: #141414;
|
||||
--colorBgSpotlight: #424242;
|
||||
--colorBgMask: rgba(0, 0, 0, 0.45);
|
||||
--colorBorder: #424242;
|
||||
--colorBorderSecondary: #303030;
|
||||
--colorFill: rgba(255, 255, 255, 0.18);
|
||||
--colorFillSecondary: rgba(255, 255, 255, 0.12);
|
||||
--colorFillTertiary: rgba(255, 255, 255, 0.08);
|
||||
--colorFillQuaternary: rgba(255, 255, 255, 0.04);
|
||||
|
||||
/* Typography */
|
||||
--fontSizeBase: 14;
|
||||
--fontSizeSM: calc(1px * var(--fontSizeBase) - 2px);
|
||||
--fontSize: calc(1px * var(--fontSizeBase));
|
||||
--fontSizeLG: calc(1px * var(--fontSizeBase) + 2px);
|
||||
--fontSizeXL: calc(1px * var(--fontSizeBase) + 4px);
|
||||
|
||||
|
||||
/* Spacing */
|
||||
--marginBase: 4;
|
||||
--marginXXS: calc(1px * var(--marginBase));
|
||||
--marginXS: calc(2px * var(--marginBase));
|
||||
--marginSM: calc(3px * var(--marginBase));
|
||||
--margin: calc(4px * var(--marginBase));
|
||||
--marginMD: calc(5px * var(--marginBase));
|
||||
--marginLG: calc(6px * var(--marginBase));
|
||||
--marginXL: calc(8px * var(--marginBase));
|
||||
--marginXXL: calc(12px * var(--marginBase));
|
||||
|
||||
--paddingBase: 4;
|
||||
--paddingXXS: calc(1px * var(--paddingBase));
|
||||
--paddingXS: calc(2px * var(--paddingBase));
|
||||
--paddingSM: calc(3px * var(--paddingBase));
|
||||
--padding: calc(4px * var(--paddingBase));
|
||||
--paddingMD: calc(5px * var(--paddingBase));
|
||||
--paddingLG: calc(6px * var(--paddingBase));
|
||||
--paddingXL: calc(8px * var(--paddingBase));
|
||||
|
||||
/* Shadow */
|
||||
--boxShadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
|
||||
0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
--boxShadowSecondary: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
|
||||
0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
|
||||
|
||||
/* Border */
|
||||
--borderRadiusBase: 2;
|
||||
--borderRadiusXS: calc(1px * var(--borderRadiusBase));
|
||||
--borderRadiusSM: calc(2px * var(--borderRadiusBase));
|
||||
--borderRadius: calc(3px * var(--borderRadiusBase));
|
||||
--borderRadiusLG: calc(4px * var(--borderRadiusBase));
|
||||
|
||||
|
||||
/* Other */
|
||||
--logo: url("https://gw.alipayobjects.com/zos/bmw-prod/9ecb2822-1592-4cb0-a087-ce0097fef2ca.svg");
|
||||
--favicon: url("https://gw.alipayobjects.com/zos/bmw-prod/51a51720-8a30-4430-b6c9-be5712364f04.svg");
|
||||
--galleryBackground: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAIKADAAQAAAABAAAAIAAAAACPTkDJAAAAZUlEQVRIDe2VMQoAMAgDa9/g/1/oIzrpZBCh2dLFkkoDF0Fz99OdiOjks+2/7S8fRRmMMIVoRGSoYzvvqF8ZIMKlC1GhQBc6IkPzq32QmdAzkEGihpWOSPsAss8HegYySNSw0hE9WQ4StafZFqkAAAAASUVORK5CYII=)
|
||||
0% 0% / 20px;
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
.dark {
|
||||
/* Colors */
|
||||
--neutral-50: var(--colorText);
|
||||
--neutral-100: var(--colorText);
|
||||
--neutral-200: var(--colorTextSecondary);
|
||||
--neutral-300: var(--colorTextTertiary);
|
||||
--neutral-400: var(--colorTextQuaternary);
|
||||
--neutral-500: var(--colorFill);
|
||||
--neutral-600: var(--colorFillSecondary);
|
||||
--neutral-700: var(--colorFillTertiary);
|
||||
--neutral-800: var(--colorFillQuaternary);
|
||||
--neutral-900: var(--colorBgElevated);
|
||||
--neutral-950: var(--colorBgContainer);
|
||||
|
||||
--primary-50: #eff6ff;
|
||||
--primary-100: #dbeafe;
|
||||
--primary-200: #bfdbfe;
|
||||
--primary-300: #93c5fd;
|
||||
--primary-400: var(--colorPrimaryTextHover);
|
||||
--primary-500: var(--colorPrimaryText);
|
||||
--primary-600: var(--colorPrimary);
|
||||
--primary-700: var(--colorPrimary);
|
||||
--primary-800: var(--colorPrimaryBorder);
|
||||
--primary-900: var(--colorPrimaryBgHover);
|
||||
--primary-950: var(--colorPrimaryBg);
|
||||
|
||||
--secondary-50: #eff6ff;
|
||||
--secondary-100: #dbeafe;
|
||||
--secondary-200: #bfdbfe;
|
||||
--secondary-300: #93c5fd;
|
||||
--secondary-400: var(--colorPrimaryTextHover);
|
||||
--secondary-500: var(--colorPrimaryText);
|
||||
--secondary-600: var(--colorPrimary);
|
||||
--secondary-700: var(--colorPrimary);
|
||||
--secondary-800: var(--colorPrimaryBorder);
|
||||
--secondary-900: var(--colorPrimaryBgHover);
|
||||
--secondary-950: var(--colorPrimaryBg);
|
||||
|
||||
--error-text-color: #ef4444;
|
||||
--error-background-fill: var(--colorErrorBg);
|
||||
|
||||
--background-fill-primary: var(--neutral-950);
|
||||
--background-fill-secondary: var(--neutral-900);
|
||||
--stat-background-fill: var(--primary-500);
|
||||
|
||||
--link-text-color-active: var(--secondary-500);
|
||||
--link-text-color: var(--secondary-500);
|
||||
--link-text-color-hover: var(--secondary-400);
|
||||
--link-text-color-visited: var(--secondary-600);
|
||||
|
||||
--color-accent: var(--primary-500);
|
||||
--color-accent-soft: var(--neutral-700);
|
||||
|
||||
--loader-color: var(--color-accent);
|
||||
|
||||
/* Typography */
|
||||
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
|
||||
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--font-mono: "Hack", "IBM Plex Mono", "ui-monospace", "Consolas", monospace;
|
||||
--prose-header-text-weight: 600;
|
||||
--prose-text-weight: 400;
|
||||
--section-header-text-weight: 400;
|
||||
--text-lg: var(--fontSizeLG);
|
||||
--text-md: var(--fontSize);
|
||||
--text-sm: var(--fontSizeSM);
|
||||
--text-xl: var(--fontSizeXL);
|
||||
--text-xs: var(--fontSizeSM);
|
||||
--text-xxl: var(--fontSizeXL);
|
||||
--text-xxs: var(--fontSizeSM);
|
||||
--prose-text-size: var(--text-md);
|
||||
--section-header-text-size: var(--text-md);
|
||||
|
||||
/* Spacing */
|
||||
--form-gap-width: 0px;
|
||||
--spacing-lg: 8px;
|
||||
--spacing-md: 6px;
|
||||
--spacing-sm: 4px;
|
||||
--spacing-xl: 10px;
|
||||
--spacing-xs: 2px;
|
||||
--spacing-xxl: 16px;
|
||||
--spacing-xxs: 1px;
|
||||
--layout-gap: var(--spacing-xxl);
|
||||
|
||||
/* Border */
|
||||
--error-border-width: 1px;
|
||||
--radius-lg: var(--borderRadiusLG);
|
||||
--radius-md: var(--borderRadius);
|
||||
--radius-sm: var(--borderRadiusSM);
|
||||
--radius-xl: var(--borderRadiusXS);
|
||||
--radius-xs: var(--borderRadiusSM);
|
||||
--radius-xxl: var(--borderRadiusLG);
|
||||
--radius-xxs: var(--borderRadiusXS);
|
||||
--border-color-accent: var(--neutral-600);
|
||||
--border-color-primary: var(--neutral-700);
|
||||
--error-border-color: var(--border-color-primary);
|
||||
--container-radius: var(--radius-lg);
|
||||
--embed-radius: var(--radius-lg);
|
||||
|
||||
/* BoxShadow */
|
||||
--shadow-spread: 1px;
|
||||
--shadow-drop: var(--boxShadow);
|
||||
--shadow-drop-lg: var(--boxShadowSecondary);
|
||||
--shadow-inset: var(--boxShadow) inset;
|
||||
|
||||
/* Body */
|
||||
--body-text-weight: 400;
|
||||
--body-background-fill: var(--background-fill-primary);
|
||||
--body-text-color: var(--neutral-100);
|
||||
--body-text-color-subdued: var(--neutral-400);
|
||||
--body-text-size: var(--text-md);
|
||||
|
||||
/* Block */
|
||||
--block-border-width: 1px;
|
||||
--block-info-text-weight: 400;
|
||||
--block-label-border-width: 1px;
|
||||
--block-label-margin: 0;
|
||||
--block-label-text-weight: 400;
|
||||
--block-shadow: none;
|
||||
--block-title-background-fill: none;
|
||||
--block-title-border-color: none;
|
||||
--block-title-border-width: 0px;
|
||||
--block-title-padding: 0;
|
||||
--block-title-radius: none;
|
||||
--block-title-text-weight: 400;
|
||||
--block-background-fill: var(--neutral-800);
|
||||
--block-border-color: var(--border-color-primary);
|
||||
--block-info-text-color: var(--body-text-color-subdued);
|
||||
--block-label-background-fill: var(--background-fill-secondary);
|
||||
--block-label-border-color: var(--border-color-primary);
|
||||
--block-label-text-color: var(--neutral-200);
|
||||
--block-title-text-color: var(--neutral-200);
|
||||
--block-info-text-size: var(--text-sm);
|
||||
--block-label-padding: var(--spacing-sm) var(--spacing-lg);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px);
|
||||
--block-label-text-size: var(--text-sm);
|
||||
--block-padding: var(--spacing-xl) calc(var(--spacing-xl) + 2px);
|
||||
--block-radius: var(--radius-lg);
|
||||
--block-title-text-size: var(--text-md);
|
||||
|
||||
/* Panel */
|
||||
--panel-border-width: 0;
|
||||
--panel-background-fill: var(--background-fill-secondary);
|
||||
--panel-border-color: var(--border-color-primary);
|
||||
|
||||
/* Button */
|
||||
--button-primary-text-color: white;
|
||||
--button-secondary-text-color: white;
|
||||
--button-large-text-weight: 600;
|
||||
--button-shadow: none;
|
||||
--button-shadow-active: none;
|
||||
--button-shadow-hover: none;
|
||||
--button-small-text-weight: 400;
|
||||
--button-transition: background-color 0.2s ease;
|
||||
--button-border-width: var(--input-border-width);
|
||||
--button-cancel-background-fill: var(--button-secondary-background-fill);
|
||||
--button-cancel-background-fill-hover: var(--button-cancel-background-fill);
|
||||
--button-cancel-border-color: var(--button-secondary-border-color);
|
||||
--button-cancel-border-color-hover: var(--button-cancel-border-color);
|
||||
--button-cancel-text-color: var(--button-secondary-text-color);
|
||||
--button-cancel-text-color-hover: var(--button-cancel-text-color);
|
||||
--button-primary-background-fill: var(--primary-700);
|
||||
--button-primary-background-fill-hover: var(--button-primary-background-fill);
|
||||
--button-primary-border-color: var(--primary-600);
|
||||
--button-primary-border-color-hover: var(--button-primary-border-color);
|
||||
--button-primary-text-color-hover: var(--button-primary-text-color);
|
||||
--button-secondary-background-fill: var(--neutral-600);
|
||||
--button-secondary-background-fill-hover: var(
|
||||
--button-secondary-background-fill
|
||||
);
|
||||
--button-secondary-border-color: var(--neutral-600);
|
||||
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
||||
--button-secondary-text-color-hover: var(--button-secondary-text-color);
|
||||
--button-large-padding: var(--spacing-lg) calc(2 * var(--spacing-lg));
|
||||
--button-large-radius: var(--radius-lg);
|
||||
--button-large-text-size: var(--text-lg);
|
||||
--button-small-padding: var(--spacing-sm) calc(2 * var(--spacing-sm));
|
||||
--button-small-radius: var(--radius-lg);
|
||||
--button-small-text-size: var(--text-md);
|
||||
|
||||
/* Checkbox */
|
||||
--checkbox-check: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||
--checkbox-label-shadow: none;
|
||||
--checkbox-label-text-weight: 400;
|
||||
--checkbox-background-color: var(--neutral-800);
|
||||
--checkbox-background-color-focus: var(--checkbox-background-color);
|
||||
--checkbox-background-color-hover: var(--checkbox-background-color);
|
||||
--checkbox-background-color-selected: var(--secondary-600);
|
||||
--checkbox-border-color: var(--neutral-700);
|
||||
--checkbox-border-color-focus: var(--secondary-500);
|
||||
--checkbox-border-color-hover: var(--neutral-600);
|
||||
--checkbox-border-color-selected: var(--secondary-600);
|
||||
--checkbox-border-width: var(--input-border-width);
|
||||
--checkbox-label-background-fill: var(--button-secondary-background-fill);
|
||||
--checkbox-label-background-fill-hover: var(
|
||||
--button-secondary-background-fill-hover
|
||||
);
|
||||
--checkbox-label-background-fill-selected: var(
|
||||
--checkbox-label-background-fill
|
||||
);
|
||||
--checkbox-label-border-color: var(--border-color-primary);
|
||||
--checkbox-label-border-color-hover: var(--checkbox-label-border-color);
|
||||
--checkbox-label-border-width: var(--input-border-width);
|
||||
--checkbox-label-text-color: var(--body-text-color);
|
||||
--checkbox-label-text-color-selected: var(--checkbox-label-text-color);
|
||||
--checkbox-border-radius: var(--radius-sm);
|
||||
--checkbox-label-gap: var(--spacing-lg);
|
||||
--checkbox-label-padding: var(--spacing-md) calc(2 * var(--spacing-md));
|
||||
--checkbox-label-text-size: var(--text-md);
|
||||
--checkbox-shadow: var(--input-shadow);
|
||||
|
||||
/* Input */
|
||||
--input-border-width: 0px;
|
||||
--input-shadow: none;
|
||||
--input-text-weight: 400;
|
||||
--input-background-fill: var(--neutral-700);
|
||||
--input-background-fill-focus: var(--secondary-600);
|
||||
--input-background-fill-hover: var(--input-background-fill);
|
||||
--input-border-color: var(--border-color-primary);
|
||||
--input-border-color-focus: var(--neutral-700);
|
||||
--input-border-color-hover: var(--input-border-color);
|
||||
--input-placeholder-color: var(--neutral-500);
|
||||
--input-padding: var(--spacing-xl);
|
||||
--input-radius: var(--radius-lg);
|
||||
--input-shadow-focus: var(--input-shadow);
|
||||
--input-text-size: var(--text-md);
|
||||
|
||||
/* Table */
|
||||
--table-border-color: var(--neutral-700);
|
||||
--table-even-background-fill: var(--neutral-950);
|
||||
--table-odd-background-fill: var(--neutral-900);
|
||||
--table-row-focus: var(--color-accent-soft);
|
||||
--table-radius: var(--radius-lg);
|
||||
|
||||
/* Other */
|
||||
--radio-circle: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
:root {
|
||||
/* Colors */
|
||||
--neutral-50: var(--colorText);
|
||||
--neutral-100: var(--colorText);
|
||||
--neutral-200: var(--colorTextSecondary);
|
||||
--neutral-300: var(--colorTextTertiary);
|
||||
--neutral-400: var(--colorTextQuaternary);
|
||||
--neutral-500: var(--colorFill);
|
||||
--neutral-600: var(--colorFillSecondary);
|
||||
--neutral-700: var(--colorFillTertiary);
|
||||
--neutral-800: var(--colorFillQuaternary);
|
||||
--neutral-900: var(--colorBgElevated);
|
||||
--neutral-950: var(--colorBgContainer);
|
||||
|
||||
--primary-50: #eff6ff;
|
||||
--primary-100: #dbeafe;
|
||||
--primary-200: #bfdbfe;
|
||||
--primary-300: #93c5fd;
|
||||
--primary-400: var(--colorPrimaryTextHover);
|
||||
--primary-500: var(--colorPrimaryText);
|
||||
--primary-600: var(--colorPrimary);
|
||||
--primary-700: var(--colorPrimary);
|
||||
--primary-800: var(--colorPrimaryBorder);
|
||||
--primary-900: var(--colorPrimaryBgHover);
|
||||
--primary-950: var(--colorPrimaryBg);
|
||||
|
||||
--secondary-50: #eff6ff;
|
||||
--secondary-100: #dbeafe;
|
||||
--secondary-200: #bfdbfe;
|
||||
--secondary-300: #93c5fd;
|
||||
--secondary-400: var(--colorPrimaryTextHover);
|
||||
--secondary-500: var(--colorPrimaryText);
|
||||
--secondary-600: var(--colorPrimary);
|
||||
--secondary-700: var(--colorPrimary);
|
||||
--secondary-800: var(--colorPrimaryBorder);
|
||||
--secondary-900: var(--colorPrimaryBgHover);
|
||||
--secondary-950: var(--colorPrimaryBg);
|
||||
|
||||
--error-background-fill: var(--colorErrorBg);
|
||||
--error-text-color: var(--colorError);
|
||||
|
||||
--background-fill-primary: var(--neutral-950);
|
||||
--background-fill-secondary: var(--neutral-900);
|
||||
--stat-background-fill: var(--primary-300);
|
||||
|
||||
--color-accent: var(--primary-500);
|
||||
--color-accent-soft: var(--primary-50);
|
||||
|
||||
--link-text-color: var(--secondary-600);
|
||||
--link-text-color-active: var(--secondary-600);
|
||||
--link-text-color-hover: var(--secondary-700);
|
||||
--link-text-color-visited: var(--secondary-500);
|
||||
|
||||
--loader-color: var(--color-accent);
|
||||
|
||||
/* Typography */
|
||||
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
|
||||
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--font-mono: "Hack", "IBM Plex Mono", "ui-monospace", "Consolas", monospace;
|
||||
--prose-header-text-weight: 600;
|
||||
--prose-text-weight: 400;
|
||||
--section-header-text-weight: 400;
|
||||
--text-lg: var(--fontSizeLG);
|
||||
--text-md: var(--fontSize);
|
||||
--text-sm: var(--fontSizeSM);
|
||||
--text-xl: var(--fontSizeXL);
|
||||
--text-xs: var(--fontSizeSM);
|
||||
--text-xxl: var(--fontSizeXL);
|
||||
--text-xxs: var(--fontSizeSM);
|
||||
--prose-text-size: var(--text-md);
|
||||
--section-header-text-size: var(--text-md);
|
||||
|
||||
/* Spacing */
|
||||
--form-gap-width: 0px;
|
||||
--spacing-lg: 8px;
|
||||
--spacing-md: 6px;
|
||||
--spacing-sm: 4px;
|
||||
--spacing-xl: 10px;
|
||||
--spacing-xs: 2px;
|
||||
--spacing-xxl: 16px;
|
||||
--spacing-xxs: 1px;
|
||||
--layout-gap: var(--spacing-xxl);
|
||||
|
||||
/* Border */
|
||||
--error-border-color: #fecaca;
|
||||
--error-border-width: 1px;
|
||||
--radius-lg: var(--borderRadiusLG);
|
||||
--radius-md: var(--borderRadius);
|
||||
--radius-sm: var(--borderRadiusSM);
|
||||
--radius-xl: var(--borderRadiusXS);
|
||||
--radius-xs: var(--borderRadiusSM);
|
||||
--radius-xxl: var(--borderRadiusLG);
|
||||
--radius-xxs: var(--borderRadiusXS);
|
||||
--border-color-accent: var(--primary-300);
|
||||
--border-color-primary: var(--neutral-200);
|
||||
--container-radius: var(--radius-lg);
|
||||
--embed-radius: var(--radius-lg);
|
||||
|
||||
/* BoxShadow */
|
||||
--shadow-spread: 1px;
|
||||
--shadow-drop: var(--boxShadow);
|
||||
--shadow-drop-lg: var(--boxShadowSecondary);
|
||||
--shadow-inset: var(--boxShadow) inset;
|
||||
|
||||
/* Body */
|
||||
--body-text-weight: 400;
|
||||
--body-background-fill: var(--background-fill-primary);
|
||||
--body-text-color: var(--neutral-800);
|
||||
--body-text-color-subdued: var(--neutral-400);
|
||||
--body-text-size: var(--text-md);
|
||||
|
||||
/* Block */
|
||||
--block-border-width: 1px;
|
||||
--block-info-text-weight: 400;
|
||||
--block-label-border-width: 1px;
|
||||
--block-label-margin: 0;
|
||||
--block-label-text-weight: 400;
|
||||
--block-shadow: none;
|
||||
--block-title-background-fill: none;
|
||||
--block-title-border-color: none;
|
||||
--block-title-border-width: 0px;
|
||||
--block-title-padding: 0;
|
||||
--block-title-radius: none;
|
||||
--block-title-text-weight: 400;
|
||||
--block-background-fill: var(--background-fill-primary);
|
||||
--block-border-color: var(--border-color-primary);
|
||||
--block-info-text-color: var(--body-text-color-subdued);
|
||||
--block-info-text-size: var(--text-sm);
|
||||
--block-label-background-fill: var(--background-fill-primary);
|
||||
--block-label-border-color: var(--border-color-primary);
|
||||
--block-label-padding: var(--spacing-sm) var(--spacing-lg);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px);
|
||||
--block-label-text-color: var(--neutral-500);
|
||||
--block-label-text-size: var(--text-sm);
|
||||
--block-padding: var(--spacing-xl) calc(var(--spacing-xl) + 2px);
|
||||
--block-radius: var(--radius-lg);
|
||||
--block-title-text-color: var(--neutral-500);
|
||||
--block-title-text-size: var(--text-md);
|
||||
|
||||
/* Panel */
|
||||
--panel-border-width: 0;
|
||||
--panel-background-fill: var(--background-fill-secondary);
|
||||
--panel-border-color: var(--border-color-primary);
|
||||
|
||||
/* Button */
|
||||
--button-large-text-weight: 600;
|
||||
--button-shadow: none;
|
||||
--button-shadow-active: none;
|
||||
--button-shadow-hover: none;
|
||||
--button-small-text-weight: 400;
|
||||
--button-transition: background-color 0.2s ease;
|
||||
--button-border-width: var(--input-border-width);
|
||||
--button-cancel-background-fill: var(--button-secondary-background-fill);
|
||||
--button-cancel-background-fill-hover: var(--button-cancel-background-fill);
|
||||
--button-cancel-border-color: var(--button-secondary-border-color);
|
||||
--button-cancel-border-color-hover: var(--button-cancel-border-color);
|
||||
--button-cancel-text-color: var(--button-secondary-text-color);
|
||||
--button-cancel-text-color-hover: var(--button-cancel-text-color);
|
||||
--button-large-padding: var(--spacing-lg) calc(2 * var(--spacing-lg));
|
||||
--button-large-radius: var(--radius-lg);
|
||||
--button-large-text-size: var(--text-lg);
|
||||
--button-primary-background-fill: var(--primary-200);
|
||||
--button-primary-background-fill-hover: var(--button-primary-background-fill);
|
||||
--button-primary-border-color: var(--primary-200);
|
||||
--button-primary-border-color-hover: var(--button-primary-border-color);
|
||||
--button-primary-text-color: var(--primary-600);
|
||||
--button-primary-text-color-hover: var(--button-primary-text-color);
|
||||
--button-secondary-background-fill: var(--neutral-200);
|
||||
--button-secondary-background-fill-hover: var(
|
||||
--button-secondary-background-fill
|
||||
);
|
||||
--button-secondary-border-color: var(--neutral-200);
|
||||
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
||||
--button-secondary-text-color: var(--neutral-700);
|
||||
--button-secondary-text-color-hover: var(--button-secondary-text-color);
|
||||
--button-small-padding: var(--spacing-sm) calc(2 * var(--spacing-sm));
|
||||
--button-small-radius: var(--radius-lg);
|
||||
--button-small-text-size: var(--text-md);
|
||||
|
||||
/* Checkbox */
|
||||
--checkbox-check: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||
--checkbox-label-shadow: none;
|
||||
--checkbox-label-text-weight: 400;
|
||||
--checkbox-background-color: var(--background-fill-primary);
|
||||
--checkbox-background-color-focus: var(--checkbox-background-color);
|
||||
--checkbox-background-color-hover: var(--checkbox-background-color);
|
||||
--checkbox-background-color-selected: var(--secondary-600);
|
||||
--checkbox-border-color: var(--neutral-300);
|
||||
--checkbox-border-color-focus: var(--secondary-500);
|
||||
--checkbox-border-color-hover: var(--neutral-300);
|
||||
--checkbox-border-color-selected: var(--secondary-600);
|
||||
--checkbox-border-radius: var(--radius-sm);
|
||||
--checkbox-border-width: var(--input-border-width);
|
||||
--checkbox-label-background-fill: var(--button-secondary-background-fill);
|
||||
--checkbox-label-background-fill-hover: var(
|
||||
--button-secondary-background-fill-hover
|
||||
);
|
||||
--checkbox-label-background-fill-selected: var(
|
||||
--checkbox-label-background-fill
|
||||
);
|
||||
--checkbox-label-border-color: var(--border-color-primary);
|
||||
--checkbox-label-border-color-hover: var(--checkbox-label-border-color);
|
||||
--checkbox-label-border-width: var(--input-border-width);
|
||||
--checkbox-label-gap: var(--spacing-lg);
|
||||
--checkbox-label-padding: var(--spacing-md) calc(2 * var(--spacing-md));
|
||||
--checkbox-label-text-color: var(--body-text-color);
|
||||
--checkbox-label-text-color-selected: var(--checkbox-label-text-color);
|
||||
--checkbox-label-text-size: var(--text-md);
|
||||
--checkbox-shadow: var(--input-shadow);
|
||||
|
||||
/* Input */
|
||||
--input-border-width: 0px;
|
||||
--input-shadow: none;
|
||||
--input-text-weight: 400;
|
||||
--input-background-fill: var(--neutral-100);
|
||||
--input-background-fill-focus: var(--secondary-500);
|
||||
--input-background-fill-hover: var(--input-background-fill);
|
||||
--input-border-color: var(--border-color-primary);
|
||||
--input-border-color-focus: var(--secondary-300);
|
||||
--input-border-color-hover: var(--input-border-color);
|
||||
--input-padding: var(--spacing-xl);
|
||||
--input-placeholder-color: var(--neutral-400);
|
||||
--input-radius: var(--radius-lg);
|
||||
--input-shadow-focus: var(--input-shadow);
|
||||
--input-text-size: var(--text-md);
|
||||
|
||||
/* Table */
|
||||
--table-even-background-fill: white;
|
||||
--table-border-color: var(--neutral-300);
|
||||
--table-odd-background-fill: var(--neutral-50);
|
||||
--table-radius: var(--radius-lg);
|
||||
--table-row-focus: var(--color-accent-soft);
|
||||
|
||||
/* Other */
|
||||
--radio-circle: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,137 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// 从本地文件读取CSS
|
||||
const cssFilePath = path.resolve(__dirname, "style.css");
|
||||
const css = fs.readFileSync(cssFilePath, "utf-8");
|
||||
|
||||
// 用于存储变量及其值的对象
|
||||
const cssVariables = {};
|
||||
|
||||
// 正则表达式用于匹配CSS变量及其值
|
||||
const cssVarRegex = /--\w+[^:]*:\s*([^;]*);/g;
|
||||
const cssVarReferenceRegex = /var\((--\w+)\)/g;
|
||||
|
||||
// 解析CSS变量及其值
|
||||
let match;
|
||||
while ((match = cssVarRegex.exec(css))) {
|
||||
const variable = match[0].split(":")[0].trim();
|
||||
const value = match[1].trim();
|
||||
cssVariables[variable] = value;
|
||||
}
|
||||
|
||||
// 对变量进行排序,确保被引用的变量在引用它的变量之前
|
||||
const sortedVariables = Object.keys(cssVariables);
|
||||
|
||||
// 按类别对变量进行分组
|
||||
const groups = {
|
||||
colors: [],
|
||||
typography: [],
|
||||
spacing: [],
|
||||
border: [],
|
||||
boxShadow: [],
|
||||
body: [],
|
||||
block: [],
|
||||
panel: [],
|
||||
button: [],
|
||||
checkbox: [],
|
||||
input: [],
|
||||
table: [],
|
||||
other: [],
|
||||
};
|
||||
|
||||
sortedVariables.forEach((variable) => {
|
||||
const value = cssVariables[variable];
|
||||
const isColor =
|
||||
value.startsWith("#") ||
|
||||
value.includes("rgb") ||
|
||||
value.includes("color") ||
|
||||
variable.includes("color") ||
|
||||
variable.includes("fill") ||
|
||||
variable.includes("neutral");
|
||||
const isTypography =
|
||||
variable.includes("text") ||
|
||||
variable.includes("font") ||
|
||||
variable.includes("prose") ||
|
||||
variable.includes("link");
|
||||
const isSpacing =
|
||||
variable.includes("spacing") ||
|
||||
variable.includes("padding") ||
|
||||
variable.includes("gap") ||
|
||||
variable.includes("margin");
|
||||
value.includes("padding") || value.includes("margin");
|
||||
const isBorder = variable.includes("radius") || variable.includes("border");
|
||||
const isBoxShadow = variable.includes("shadow");
|
||||
if (variable.includes("--body")) {
|
||||
groups.body.push(variable);
|
||||
} else if (variable.includes("--block")) {
|
||||
groups.block.push(variable);
|
||||
} else if (variable.includes("--panel")) {
|
||||
groups.panel.push(variable);
|
||||
} else if (variable.includes("--button")) {
|
||||
groups.button.push(variable);
|
||||
} else if (variable.includes("--checkbox")) {
|
||||
groups.checkbox.push(variable);
|
||||
} else if (variable.includes("--input")) {
|
||||
groups.input.push(variable);
|
||||
} else if (variable.includes("--table")) {
|
||||
groups.table.push(variable);
|
||||
} else if (isBorder) {
|
||||
groups.border.push(variable);
|
||||
} else if (isBoxShadow) {
|
||||
groups.boxShadow.push(variable);
|
||||
} else if (isColor) {
|
||||
groups.colors.push(variable);
|
||||
} else if (isTypography) {
|
||||
groups.typography.push(variable);
|
||||
} else if (isSpacing) {
|
||||
groups.spacing.push(variable);
|
||||
} else {
|
||||
groups.other.push(variable);
|
||||
}
|
||||
});
|
||||
|
||||
// 生成排序后的CSS变量
|
||||
const generateGroupCss = (groupName) => {
|
||||
const cache = groups[groupName].map(
|
||||
(variable) => `${variable}: ${cssVariables[variable]};`
|
||||
);
|
||||
const firstPart = cache.filter((item) => item.includes("var"));
|
||||
const secondPart = cache.filter((item) => !item.includes("var"));
|
||||
return [...secondPart, ...firstPart].join("\n");
|
||||
};
|
||||
|
||||
const sortedCss =
|
||||
"#output {\n" +
|
||||
`/* Colors */\n` +
|
||||
generateGroupCss("colors") +
|
||||
`\n\n/* Typography */\n` +
|
||||
generateGroupCss("typography") +
|
||||
`\n\n/* Spacing */\n` +
|
||||
generateGroupCss("spacing") +
|
||||
`\n\n/* Border */\n` +
|
||||
generateGroupCss("border") +
|
||||
`\n\n/* BoxShadow */\n` +
|
||||
generateGroupCss("boxShadow") +
|
||||
`\n\n/* Body */\n` +
|
||||
generateGroupCss("body") +
|
||||
`\n\n/* Block */\n` +
|
||||
generateGroupCss("block") +
|
||||
`\n\n/* Panel */\n` +
|
||||
generateGroupCss("panel") +
|
||||
`\n\n/* Button */\n` +
|
||||
generateGroupCss("button") +
|
||||
`\n\n/* Checkbox */\n` +
|
||||
generateGroupCss("checkbox") +
|
||||
`\n\n/* Input */\n` +
|
||||
generateGroupCss("input") +
|
||||
`\n\n/* Table */\n` +
|
||||
generateGroupCss("table") +
|
||||
`\n\n/* Other */\n` +
|
||||
generateGroupCss("other") +
|
||||
"}";
|
||||
|
||||
console.log(sortedCss);
|
||||
|
||||
// 将排序后的CSS变量写入文件
|
||||
fs.writeFileSync("sorted-css-variables.css", sortedCss);
|
||||
Loading…
Reference in New Issue