2
0
mirror of https://github.com/gradio-app/gradio.git synced 2025-04-18 12:50:30 +08:00

add ci for ui ()

* add ci for frontend

* add ci for frontend

* fix workflow

* fix format errors
This commit is contained in:
pngwn 2022-02-02 15:49:37 +00:00 committed by GitHub
parent dd94a47f59
commit 70981c3732
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 2020 additions and 736 deletions

34
.github/workflows/ui.yml vendored Normal file

@ -0,0 +1,34 @@
name: gradio-ui
on:
push:
branches:
- "master"
paths:
- "ui/**"
pull_request:
paths:
- "ui/**"
defaults:
run:
working-directory: "./ui"
jobs:
check:
name: static checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm i -g pnpm@6
- uses: actions/setup-node@v2
with:
node-version: 16
- name: "install dependencies"
run: pnpm i --frozen-lockfile
- name: "formatting check"
run: pnpm format:check
- name: "typecheck"
run: pnpm ts:check
continue-on-error: true

@ -1,2 +1,3 @@
packages/app/public/**
pnpm-workspace.yaml
pnpm-workspace.yaml
packages/app/dist/**

@ -7,7 +7,7 @@
"build": "pnpm build --filter @gradio/app",
"format:check": "prettier --check --plugin-search-dir=. .",
"format:write": "prettier --write --plugin-search-dir=. .",
"check": "svelte-check --tsconfig tsconfig.json"
"ts:check": "svelte-check --tsconfig tsconfig.json"
},
"author": "",
"license": "ISC",

@ -1,42 +1,51 @@
<!DOCTYPE html>
<html lang="en" style="min-height: 100%; margin: 0; padding: 0;">
<html lang="en" style="min-height: 100%; margin: 0; padding: 0">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script type="module" src="./src/main.js"></script>
<title>{{ config['title'] or 'Gradio' }}</title>
<meta property="og:url" content="https://gradio.app/" />
<meta property="og:type" content="website" />
<meta property="og:image" content="{{ config['thumbnail'] or '' }}" />
<meta property="og:title" content="{{ config['title'] or '' }}" />
<meta property="og:description" content="{{ config['description'] or '' }}" />
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:creator" content="@teamGradio">
<meta name="twitter:title" content="{{ config['title'] or '' }}">
<meta name="twitter:description" content="{{ config['description'] or '' }}">
<meta name="twitter:image" content="{{ config['thumbnail'] or '' }}">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-156449732-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-156449732-1');
window.gradio_mode = "app";
</script>
<script>
window.gradio_config = {{ config|tojson }};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script>
<title>Gradio</title>
</head>
<body style="height: 100%; margin: 0; padding: 0;">
<div id="root" style="height: 100%"></div>
</body>
<script type="module" src="./src/main.js"></script>
<title>{{ config['title'] or 'Gradio' }}</title>
<meta property="og:url" content="https://gradio.app/" />
<meta property="og:type" content="website" />
<meta property="og:image" content="{{ config['thumbnail'] or '' }}" />
<meta property="og:title" content="{{ config['title'] or '' }}" />
<meta
property="og:description"
content="{{ config['description'] or '' }}"
/>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:creator" content="@teamGradio" />
<meta name="twitter:title" content="{{ config['title'] or '' }}" />
<meta
name="twitter:description"
content="{{ config['description'] or '' }}"
/>
<meta name="twitter:image" content="{{ config['thumbnail'] or '' }}" />
<script
async
src="https://www.googletagmanager.com/gtag/js?id=UA-156449732-1"
></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "UA-156449732-1");
window.gradio_mode = "app";
</script>
<script>
window.gradio_config = {{ config|tojson }};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script>
<title>Gradio</title>
</head>
<body style="height: 100%; margin: 0; padding: 0">
<div id="root" style="height: 100%"></div>
</body>
</html>

@ -1,4 +1,8 @@
module.exports = {
extract: "themes.css",
plugins: [require("tailwindcss"), require("postcss-nested"), require("autoprefixer")]
plugins: [
require("tailwindcss"),
require("postcss-nested"),
require("autoprefixer")
]
};

@ -1,5 +1,8 @@
<script>
import { input_component_map, output_component_map } from "./components/directory.js";
import {
input_component_map,
output_component_map
} from "./components/directory.js";
import { deepCopy } from "./components/utils/helpers.js";
import ExampleSet from "./ExampleSet.svelte";
@ -30,16 +33,22 @@
let timer = null;
let timer_start = 0;
let timer_diff = 0;
let avg_duration = Array.isArray(avg_durations) ? this.props.avg_durations[0] : null;
let avg_duration = Array.isArray(avg_durations)
? this.props.avg_durations[0]
: null;
const setValues = (index, value) => {
input_values[index] = value;
};
const setExampleId = async (example_id) => {
input_components.forEach(async (input_component, i) => {
const process_example = input_component_map[input_component.name].process_example;
const process_example =
input_component_map[input_component.name].process_example;
if (process_example !== undefined) {
input_values[i] = await process_example(examples[example_id][i], examples_dir);
input_values[i] = await process_example(
examples[example_id][i],
examples_dir
);
} else {
input_values[i] = examples[example_id][i];
}
@ -65,7 +74,10 @@
startTimer();
fn("predict", { data: input_values })
.then((output) => {
if (state !== "PENDING" || submission_count_at_click !== submission_count) {
if (
state !== "PENDING" ||
submission_count_at_click !== submission_count
) {
return;
}
stopTimer();
@ -79,7 +91,10 @@
state = "COMPLETE";
})
.catch((e) => {
if (state !== "PENDING" || submission_count_at_click !== submission_count) {
if (
state !== "PENDING" ||
submission_count_at_click !== submission_count
) {
return;
}
stopTimer();
@ -120,7 +135,10 @@
<div class="gradio-interface" {theme}>
<div class="panels flex flex-wrap justify-center gap-4">
<div class="panel flex-1">
<div class="component-set p-2 rounded flex flex-col flex-1 gap-2" style="min-height: 36px">
<div
class="component-set p-2 rounded flex flex-col flex-1 gap-2"
style="min-height: 36px"
>
{#each input_components as input_component, i}
<div class="component" key={i}>
<div class="panel-header mb-1.5">{input_component.label}</div>
@ -217,7 +235,13 @@
</div>
</div>
{#if examples}
<ExampleSet {examples} {input_components} {theme} {examples_dir} {setExampleId} />
<ExampleSet
{examples}
{input_components}
{theme}
{examples_dir}
{setExampleId}
/>
{/if}
</div>
@ -225,11 +249,21 @@
.pending {
@keyframes ld-breath {
0% {
animation-timing-function: cubic-bezier(0.9647, 0.2413, -0.0705, 0.7911);
animation-timing-function: cubic-bezier(
0.9647,
0.2413,
-0.0705,
0.7911
);
transform: scale(0.9);
}
51% {
animation-timing-function: cubic-bezier(0.9226, 0.2631, -0.0308, 0.7628);
animation-timing-function: cubic-bezier(
0.9226,
0.2631,
-0.0308,
0.7628
);
transform: scale(1.2);
}
100% {

@ -18,7 +18,10 @@ export const fn = async (api_endpoint, action, data, queue, queue_callback) => {
data["action"] = action;
const output = await postData(api_endpoint + "queue/push/", data);
const output_json = await output.json();
let [hash, queue_position] = [output_json["hash"], output_json["queue_position"]];
let [hash, queue_position] = [
output_json["hash"],
output_json["queue_position"]
];
queue_callback(queue_position, /*is_initial=*/ true);
let status = "UNKNOWN";
while (status != "COMPLETE" && status != "FAILED") {

@ -121,7 +121,12 @@
</Upload>
{/if}
{:else}
<ModifyUpload {clear} edit={() => (mode = "edit")} absolute={false} {theme} />
<ModifyUpload
{clear}
edit={() => (mode = "edit")}
absolute={false}
{theme}
/>
<audio
use:loaded

@ -9,7 +9,10 @@
</audio>
<div class="interpret_range flex">
{#each interpretation as interpret_value}
<div class="flex-1 h-4" style={"background-color: " + getSaliencyColor(interpret_value)} />
<div
class="flex-1 h-4"
style={"background-color: " + getSaliencyColor(interpret_value)}
/>
{/each}
</div>
</div>

@ -5,7 +5,10 @@
</script>
<div class="input-checkbox inline-block" {theme}>
<button class="checkbox-item py-2 px-3 rounded cursor-pointer flex gap-1" class:selected={value}>
<button
class="checkbox-item py-2 px-3 rounded cursor-pointer flex gap-1"
class:selected={value}
>
<div
class="checkbox w-4 h-4 bg-white flex items-center justify-center border border-gray-400 box-border"
style={"background-color: " + getSaliencyColor(interpretation[0])}

@ -252,7 +252,12 @@
<h4 id="title">{label}</h4>
<div class="shadow overflow-hidden border-gray-200 rounded-sm relative">
<table id="grid" role="grid" aria-labelledby="title" class="min-w-full divide-y divide-gray-200 ">
<table
id="grid"
role="grid"
aria-labelledby="title"
class="min-w-full divide-y divide-gray-200 "
>
<thead class="bg-gray-50">
<tr>
{#each _headers as { value, id }, i (id)}
@ -273,7 +278,8 @@
bind:value
bind:this={els[id].input}
on:keydown={end_header_edit}
on:blur={({ currentTarget }) => currentTarget.setAttribute("tabindex", -1)}
on:blur={({ currentTarget }) =>
currentTarget.setAttribute("tabindex", -1)}
/>
{/if}
<span
@ -296,7 +302,8 @@
on:click={() => handle_cell_click(id)}
on:keydown={(e) => handle_keydown(e, i, j, id)}
bind:this={els[id].cell}
on:blur={({ currentTarget }) => currentTarget.setAttribute("tabindex", -1)}
on:blur={({ currentTarget }) =>
currentTarget.setAttribute("tabindex", -1)}
>
<div
class:border-gray-600={selected === id}
@ -309,7 +316,8 @@
tabindex="-1"
bind:value
bind:this={els[id].input}
on:blur={({ currentTarget }) => currentTarget.setAttribute("tabindex", -1)}
on:blur={({ currentTarget }) =>
currentTarget.setAttribute("tabindex", -1)}
/>
{/if}
<span

@ -4,13 +4,19 @@
</script>
<div class="input-dropdown group inline-block relative" {theme}>
<button class="selector py-2 px-3 font-semibold rounded inline-flex items-center">
<button
class="selector py-2 px-3 font-semibold rounded inline-flex items-center"
>
{value}
<svg class="caret ml-2 fill-current h-4 w-4" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
<path
d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"
/>
</svg>
</button>
<div class="dropdown-menu-holder absolute hidden group-hover:block pt-1 z-10 bg-none">
<div
class="dropdown-menu-holder absolute hidden group-hover:block pt-1 z-10 bg-none"
>
<ul class="dropdown-menu max-h-80 overflow-y-auto">
{#each choices as choice, i}
<li

@ -14,7 +14,9 @@
Click to Upload
</Upload>
{:else}
<div class="file-preview w-full flex flex-row flex-wrap justify-center items-center relative">
<div
class="file-preview w-full flex flex-row flex-wrap justify-center items-center relative"
>
<ModifyUpload clear={() => setValue(null)} {theme} />
<svg
xmlns="http://www.w3.org/2000/svg"

@ -27,7 +27,10 @@
class:h-80={source !== "webcam"}
>
{#if source === "canvas"}
<ModifySketch on:undo={() => sketch.undo()} on:clear={() => sketch.clear()} />
<ModifySketch
on:undo={() => sketch.undo()}
on:clear={() => sketch.clear()}
/>
<Sketch bind:this={sketch} on:change={({ detail }) => setValue(detail)} />
{:else if value === null}
{#if source === "upload"}
@ -48,9 +51,17 @@
<Cropper image={value} on:crop={({ detail }) => setValue(detail)} />
{:else if tool === "editor"}
{#if mode === "edit"}
<ImageEditor {value} on:cancel={() => (mode = "view")} on:save={handle_save} />
<ImageEditor
{value}
on:cancel={() => (mode = "view")}
on:save={handle_save}
/>
{/if}
<ModifyUpload edit={() => (mode = "edit")} clear={() => setValue(null)} {theme} />
<ModifyUpload
edit={() => (mode = "edit")}
clear={() => setValue(null)}
{theme}
/>
<img class="w-full h-full object-contain" src={value} alt="" />
{/if}

@ -32,13 +32,24 @@
image.naturalHeight
);
if (shape) {
size = getObjectFitSize(true, size.width, size.height, shape[0], shape[1]);
size = getObjectFitSize(
true,
size.width,
size.height,
shape[0],
shape[1]
);
}
let width = size.width;
let height = size.height;
saliency_layer.setAttribute("height", height);
saliency_layer.setAttribute("width", width);
paintSaliency(interpretation, saliency_layer.getContext("2d"), width, height);
paintSaliency(
interpretation,
saliency_layer.getContext("2d"),
width,
height
);
});
</script>

@ -7,7 +7,10 @@
<div class="input-number">
<div class="interpret_range flex">
{#each interpretation as interpret_value}
<div class="flex-1" style={"background-color: " + getSaliencyColor(interpret_value[1])}>
<div
class="flex-1"
style={"background-color: " + getSaliencyColor(interpret_value[1])}
>
{interpret_value[0]}
</div>
{/each}

@ -17,7 +17,10 @@
/>
<div class="interpret_range flex">
{#each interpretation as interpret_value}
<div class="flex-1 h-4" style={"background-color: " + getSaliencyColor(interpret_value)} />
<div
class="flex-1 h-4"
style={"background-color: " + getSaliencyColor(interpret_value)}
/>
{/each}
</div>
<div class="value inline-block mx-auto mt-1 px-2 py-0.5 rounded">{value}</div>

@ -55,7 +55,12 @@
</script>
{#if _value}
<Chart value={_value} {y} {x} on:process={({ detail: { x, y } }) => setValue(make_dict(x, y))} />
<Chart
value={_value}
{y}
{x}
on:process={({ detail: { x, y } }) => setValue(make_dict(x, y))}
/>
{/if}
{#if !value}
<Upload

@ -29,13 +29,19 @@
{/each}
<div class="carousel-control flex gap-4 justify-center items-center my-1">
<button on:click={prev}>
<svg class="caret h-3 mt-0.5 fill-current" viewBox="0 0 9.1457395 15.999842">
<svg
class="caret h-3 mt-0.5 fill-current"
viewBox="0 0 9.1457395 15.999842"
>
<path
d="M 0.32506616,7.2360106 7.1796187,0.33129769 c 0.4360247,-0.439451 1.1455702,-0.442056 1.5845974,-0.0058 0.4390612,0.435849 0.441666,1.14535901 0.00582,1.58438501 l -6.064985,6.1096644 6.10968,6.0646309 c 0.4390618,0.436026 0.4416664,1.145465 0.00582,1.584526 -0.4358485,0.439239 -1.1453586,0.441843 -1.5845975,0.0058 L 0.33088256,8.8203249 C 0.11135166,8.6022941 0.00105996,8.3161928 7.554975e-6,8.0295489 -0.00104244,7.7427633 0.10735446,7.4556467 0.32524356,7.2361162"
/>
</svg>
</button>
<div class="carousel_index text-xl text-center font-semibold" style="min-width: 60px">
<div
class="carousel_index text-xl text-center font-semibold"
style="min-width: 60px"
>
{carousel_index + 1} / {value.length}
</div>
<button on:click={next}>

@ -47,17 +47,18 @@
title={category}
style={category === null
? ""
: `color: ${color_map[category]}; background-color: ${color_map[category].replace(
"1)",
"var(--tw-bg-opacity))"
)}`}
: `color: ${color_map[category]}; background-color: ${color_map[
category
].replace("1)", "var(--tw-bg-opacity))")}`}
key={i}
>
<span class="text dark:text-white">{text}</span>
{#if !show_legend && category !== null}
<span
class="inline-category text-xs text-white ml-0.5 px-0.5 rounded-sm"
style={category === null ? "" : `background-color: ${color_map[category]}`}
style={category === null
? ""
: `background-color: ${color_map[category]}`}
>
{category}
</span>

@ -62,7 +62,12 @@
&#125;
{/if}
{:else if value === null}
<div class="json-item inline text-gray-500 dark:text-gray-400" item-type="null">null</div>
<div
class="json-item inline text-gray-500 dark:text-gray-400"
item-type="null"
>
null
</div>
{:else if typeof value === "string"}
<div class="json-item inline text-green-500" item-type="string">
"{value}"

@ -26,7 +26,9 @@
{#each value.confidences as confidence_set, i}
<div
class="confidence flex justify-end items-center overflow-hidden whitespace-nowrap h-7 mb-2 px-1"
style={"min-width: calc(" + Math.round(confidence_set.confidence * 100) + "% - 12px)"}
style={"min-width: calc(" +
Math.round(confidence_set.confidence * 100) +
"% - 12px)"}
key={i}
>
{Math.round(confidence_set.confidence * 100) + "%"}

@ -3,14 +3,32 @@
export let absolute = true;
</script>
<div class="modify-upload z-10 top-0 right-0 flex justify-end" class:absolute {theme}>
<div
class="modify-upload z-10 top-0 right-0 flex justify-end"
class:absolute
{theme}
>
{#if edit}
<button class="edit bg-opacity-30 hover:bg-opacity-100 transition p-1" on:click={edit}>
<img class="h-4 filter dark:invert" src="static/img/edit.svg" alt="Edit" />
<button
class="edit bg-opacity-30 hover:bg-opacity-100 transition p-1"
on:click={edit}
>
<img
class="h-4 filter dark:invert"
src="static/img/edit.svg"
alt="Edit"
/>
</button>
{/if}
<button class="clear bg-opacity-30 hover:bg-opacity-100 transition p-1" on:click={clear}>
<img class="h-4 filter dark:invert" src="static/img/clear.svg" alt="Clear" />
<button
class="clear bg-opacity-30 hover:bg-opacity-100 transition p-1"
on:click={clear}
>
<img
class="h-4 filter dark:invert"
src="static/img/clear.svg"
alt="Clear"
/>
</button>
</div>

@ -32,7 +32,13 @@
if (video_source.videoWidth && video_source.videoHeight) {
canvas.width = video_source.videoWidth;
canvas.height = video_source.videoHeight;
context.drawImage(video_source, 0, 0, video_source.videoWidth, video_source.videoHeight);
context.drawImage(
video_source,
0,
0,
video_source.videoWidth,
video_source.videoHeight
);
var data = canvas.toDataURL("image/png");
dispatch("capture", data);

@ -36,7 +36,17 @@ export const getNextColor = (index, alpha) => {
} else {
var color_set = [randInt(64, 196), randInt(64, 196), randInt(64, 196)];
}
return "rgba(" + color_set[0] + ", " + color_set[1] + ", " + color_set[2] + ", " + alpha + ")";
return (
"rgba(" +
color_set[0] +
", " +
color_set[1] +
", " +
color_set[2] +
", " +
alpha +
")"
);
};
export const prettyBytes = (bytes) => {

@ -510,7 +510,9 @@ body > textarea {
white-space: nowrap;
}
.tui-image-editor-container .tui-image-editor-menu > .tui-image-editor-item,
.tui-image-editor-container .tui-image-editor-help-menu > .tui-image-editor-item {
.tui-image-editor-container
.tui-image-editor-help-menu
> .tui-image-editor-item {
position: relative;
display: inline-block;
border-radius: 2px;
@ -556,8 +558,12 @@ body > textarea {
left: 0;
min-width: 24px;
}
.tui-image-editor-container .tui-image-editor-menu > .tui-image-editor-item.active,
.tui-image-editor-container .tui-image-editor-help-menu > .tui-image-editor-item.active {
.tui-image-editor-container
.tui-image-editor-menu
> .tui-image-editor-item.active,
.tui-image-editor-container
.tui-image-editor-help-menu
> .tui-image-editor-item.active {
background-color: #fff;
transition: all 0.3s ease;
}
@ -571,8 +577,12 @@ body > textarea {
height: 100%;
border: 1px solid rgba(255, 255, 255, 0.7);
}
.tui-image-editor-container .tui-image-editor-main.tui-image-editor-menu-flip .tui-image-editor,
.tui-image-editor-container .tui-image-editor-main.tui-image-editor-menu-rotate .tui-image-editor {
.tui-image-editor-container
.tui-image-editor-main.tui-image-editor-menu-flip
.tui-image-editor,
.tui-image-editor-container
.tui-image-editor-main.tui-image-editor-menu-rotate
.tui-image-editor {
transition: none;
}
.tui-image-editor-container
@ -605,19 +615,31 @@ body > textarea {
border-radius: 100%;
background-color: #fff;
}
.tui-image-editor-container .tui-image-editor-grid-visual table td.dot.left-top:before {
.tui-image-editor-container
.tui-image-editor-grid-visual
table
td.dot.left-top:before {
top: -5px;
left: -5px;
}
.tui-image-editor-container .tui-image-editor-grid-visual table td.dot.right-top:before {
.tui-image-editor-container
.tui-image-editor-grid-visual
table
td.dot.right-top:before {
top: -5px;
right: -5px;
}
.tui-image-editor-container .tui-image-editor-grid-visual table td.dot.left-bottom:before {
.tui-image-editor-container
.tui-image-editor-grid-visual
table
td.dot.left-bottom:before {
bottom: -5px;
left: -5px;
}
.tui-image-editor-container .tui-image-editor-grid-visual table td.dot.right-bottom:before {
.tui-image-editor-container
.tui-image-editor-grid-visual
table
td.dot.right-bottom:before {
bottom: -5px;
right: -5px;
}
@ -637,7 +659,10 @@ body > textarea {
> use.active {
display: block;
}
.tui-image-editor-container .tui-image-editor-submenu .tui-image-editor-submenu-item li {
.tui-image-editor-container
.tui-image-editor-submenu
.tui-image-editor-submenu-item
li {
display: inline-block;
vertical-align: top;
}
@ -665,7 +690,11 @@ body > textarea {
.tui-image-editor-button.preset {
margin: 0 9px 20px 5px;
}
.tui-image-editor-container .tui-image-editor-submenu .tui-image-editor-submenu-item label > span {
.tui-image-editor-container
.tui-image-editor-submenu
.tui-image-editor-submenu-item
label
> span {
display: inline-block;
cursor: pointer;
padding-top: 5px;
@ -688,7 +717,9 @@ body > textarea {
display: none;
vertical-align: bottom;
}
.tui-image-editor-container .tui-image-editor-submenu .tui-image-editor-submenu-style {
.tui-image-editor-container
.tui-image-editor-submenu
.tui-image-editor-submenu-style {
opacity: 0.95;
z-index: -1;
position: absolute;
@ -722,7 +753,10 @@ body > textarea {
.tui-image-editor-container .tui-image-editor-submenu-align:first-child {
margin-right: 0;
}
.tui-image-editor-container .tui-image-editor-submenu-align:first-child label > span {
.tui-image-editor-container
.tui-image-editor-submenu-align:first-child
label
> span {
width: 70px;
}
.tui-image-editor-container
@ -829,7 +863,10 @@ body > textarea {
cursor: auto;
transform: translateX(calc(-50% + 12px));
}
.tui-image-editor-container .tui-image-editor-help-menu .tie-panel-history .history-list {
.tui-image-editor-container
.tui-image-editor-help-menu
.tie-panel-history
.history-list {
height: 268px;
padding: 0;
overflow: hidden scroll;
@ -927,10 +964,16 @@ body > textarea {
color: #333;
opacity: 0.3;
}
.tui-image-editor-container .tui-image-editor-help-menu .opened .tie-panel-history {
.tui-image-editor-container
.tui-image-editor-help-menu
.opened
.tie-panel-history {
display: block;
}
.tui-image-editor-container .tui-image-editor-help-menu .opened .tie-panel-history:before {
.tui-image-editor-container
.tui-image-editor-help-menu
.opened
.tie-panel-history:before {
content: "";
position: absolute;
display: inline-block;
@ -1008,7 +1051,9 @@ body > textarea {
appearance: none;
padding: 0 7px 0 10px;
}
.tui-image-editor-container .tui-image-editor-selectlist-wrap .tui-image-editor-selectlist {
.tui-image-editor-container
.tui-image-editor-selectlist-wrap
.tui-image-editor-selectlist {
display: none;
position: relative;
top: -1px;
@ -1017,7 +1062,10 @@ body > textarea {
border-top: 0;
padding: 4px 0;
}
.tui-image-editor-container .tui-image-editor-selectlist-wrap .tui-image-editor-selectlist li {
.tui-image-editor-container
.tui-image-editor-selectlist-wrap
.tui-image-editor-selectlist
li {
display: block;
text-align: left;
padding: 7px 10px;
@ -1040,12 +1088,20 @@ body > textarea {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAHlJREFUKBVjYBgFOEOAEVkmPDxc89+/f6eAYjzI4kD2FyYmJrOVK1deh4kzwRggGiQBVJCELAZig8SQNYHEmEEEMrh69eo1HR0dfqCYJUickZGxf9WqVf3IakBsFBthklpaWmVA9mEQhrJhUoTp0NBQCRAmrHL4qgAAuu4cWZOZIGsAAAAASUVORK5CYII=);
background-size: cover;
}
.tui-image-editor-container .tui-image-editor-selectlist-wrap select::-ms-expand {
.tui-image-editor-container
.tui-image-editor-selectlist-wrap
select::-ms-expand {
display: none;
}
.tui-image-editor-container .tui-image-editor-virtual-range-bar .tui-image-editor-disabled,
.tui-image-editor-container .tui-image-editor-virtual-range-subbar .tui-image-editor-disabled,
.tui-image-editor-container .tui-image-editor-virtual-range-pointer .tui-image-editor-disabled {
.tui-image-editor-container
.tui-image-editor-virtual-range-bar
.tui-image-editor-disabled,
.tui-image-editor-container
.tui-image-editor-virtual-range-subbar
.tui-image-editor-disabled,
.tui-image-editor-container
.tui-image-editor-virtual-range-pointer
.tui-image-editor-disabled {
backbround-color: #f00;
}
.tui-image-editor-container .tui-image-editor-range {
@ -1083,27 +1139,38 @@ body > textarea {
display: inline-block;
margin-left: 4px;
}
.tui-image-editor-container .tui-image-editor-range-wrap.short .tui-image-editor-range {
.tui-image-editor-container
.tui-image-editor-range-wrap.short
.tui-image-editor-range {
width: 100px;
}
.tui-image-editor-container .color-picker-control .tui-image-editor-range {
width: 108px;
margin-left: 10px;
}
.tui-image-editor-container .color-picker-control .tui-image-editor-virtual-range-pointer {
.tui-image-editor-container
.color-picker-control
.tui-image-editor-virtual-range-pointer {
background-color: #333;
}
.tui-image-editor-container .color-picker-control .tui-image-editor-virtual-range-bar {
.tui-image-editor-container
.color-picker-control
.tui-image-editor-virtual-range-bar {
background-color: #ccc;
}
.tui-image-editor-container .color-picker-control .tui-image-editor-virtual-range-subbar {
.tui-image-editor-container
.color-picker-control
.tui-image-editor-virtual-range-subbar {
background-color: #606060;
}
.tui-image-editor-container .tui-image-editor-range-wrap.tui-image-editor-newline.short {
.tui-image-editor-container
.tui-image-editor-range-wrap.tui-image-editor-newline.short {
margin-top: -2px;
margin-left: 19px;
}
.tui-image-editor-container .tui-image-editor-range-wrap.tui-image-editor-newline.short label {
.tui-image-editor-container
.tui-image-editor-range-wrap.tui-image-editor-newline.short
label {
color: #8e8e8e;
font-weight: normal;
}
@ -1200,26 +1267,46 @@ body > textarea {
width: 24px;
height: 1px;
}
.tui-image-editor-container.left .tui-image-editor-submenu .tui-image-editor-partition,
.tui-image-editor-container.right .tui-image-editor-submenu .tui-image-editor-partition {
.tui-image-editor-container.left
.tui-image-editor-submenu
.tui-image-editor-partition,
.tui-image-editor-container.right
.tui-image-editor-submenu
.tui-image-editor-partition {
display: block;
width: 75%;
margin: auto;
}
.tui-image-editor-container.left .tui-image-editor-submenu .tui-image-editor-partition > div,
.tui-image-editor-container.right .tui-image-editor-submenu .tui-image-editor-partition > div {
.tui-image-editor-container.left
.tui-image-editor-submenu
.tui-image-editor-partition
> div,
.tui-image-editor-container.right
.tui-image-editor-submenu
.tui-image-editor-partition
> div {
border-left: 0;
height: 10px;
border-bottom: 1px solid #3c3c3c;
width: 100%;
margin: 0;
}
.tui-image-editor-container.left .tui-image-editor-submenu .tui-image-editor-submenu-align,
.tui-image-editor-container.right .tui-image-editor-submenu .tui-image-editor-submenu-align {
.tui-image-editor-container.left
.tui-image-editor-submenu
.tui-image-editor-submenu-align,
.tui-image-editor-container.right
.tui-image-editor-submenu
.tui-image-editor-submenu-align {
margin-right: 0;
}
.tui-image-editor-container.left .tui-image-editor-submenu .tui-image-editor-submenu-item li,
.tui-image-editor-container.right .tui-image-editor-submenu .tui-image-editor-submenu-item li {
.tui-image-editor-container.left
.tui-image-editor-submenu
.tui-image-editor-submenu-item
li,
.tui-image-editor-container.right
.tui-image-editor-submenu
.tui-image-editor-submenu-item
li {
margin-top: 15px;
}
.tui-image-editor-container.left
@ -1239,7 +1326,9 @@ body > textarea {
width: 182px;
white-space: normal;
}
.tui-image-editor-container.left .tui-image-editor-range-wrap.tui-image-editor-newline label.range,
.tui-image-editor-container.left
.tui-image-editor-range-wrap.tui-image-editor-newline
label.range,
.tui-image-editor-container.right
.tui-image-editor-range-wrap.tui-image-editor-newline
label.range {
@ -1355,7 +1444,10 @@ body > textarea {
.tui-image-editor-container .tui-image-editor-help-menu.top .tie-panel-history {
top: 45px;
}
.tui-image-editor-container .tui-image-editor-help-menu.top .opened .tie-panel-history:before {
.tui-image-editor-container
.tui-image-editor-help-menu.top
.opened
.tie-panel-history:before {
border-right: 8px solid transparent;
border-left: 8px solid transparent;
border-bottom: 8px solid #fff;
@ -1395,10 +1487,15 @@ body > textarea {
left: 50%;
transform: translateX(-50%);
}
.tui-image-editor-container .tui-image-editor-help-menu.bottom .tie-panel-history {
.tui-image-editor-container
.tui-image-editor-help-menu.bottom
.tie-panel-history {
bottom: 45px;
}
.tui-image-editor-container .tui-image-editor-help-menu.bottom .opened .tie-panel-history:before {
.tui-image-editor-container
.tui-image-editor-help-menu.bottom
.opened
.tie-panel-history:before {
border-right: 8px solid transparent;
border-left: 8px solid transparent;
border-top: 8px solid #fff;
@ -1440,18 +1537,25 @@ body > textarea {
top: 50%;
transform: translateY(-50%);
}
.tui-image-editor-container .tui-image-editor-help-menu.left .tie-panel-history {
.tui-image-editor-container
.tui-image-editor-help-menu.left
.tie-panel-history {
left: 140px;
top: -4px;
}
.tui-image-editor-container .tui-image-editor-help-menu.left .opened .tie-panel-history:before {
.tui-image-editor-container
.tui-image-editor-help-menu.left
.opened
.tie-panel-history:before {
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
border-right: 8px solid #fff;
left: -8px;
top: 14px;
}
.tui-image-editor-container .tui-image-editor-help-menu.left .tui-image-editor-item {
.tui-image-editor-container
.tui-image-editor-help-menu.left
.tui-image-editor-item {
margin: 4px auto;
padding: 6px 8px;
}
@ -1488,18 +1592,25 @@ body > textarea {
top: 50%;
transform: translateY(-50%);
}
.tui-image-editor-container .tui-image-editor-help-menu.right .tie-panel-history {
.tui-image-editor-container
.tui-image-editor-help-menu.right
.tie-panel-history {
right: -30px;
top: -4px;
}
.tui-image-editor-container .tui-image-editor-help-menu.right .opened .tie-panel-history:before {
.tui-image-editor-container
.tui-image-editor-help-menu.right
.opened
.tie-panel-history:before {
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
border-left: 8px solid #fff;
right: -8px;
top: 14px;
}
.tui-image-editor-container .tui-image-editor-help-menu.right .tui-image-editor-item {
.tui-image-editor-container
.tui-image-editor-help-menu.right
.tui-image-editor-item {
margin: 4px auto;
padding: 6px 8px;
}
@ -1549,14 +1660,38 @@ body > textarea {
.tui-image-editor-container .tui-image-editor-controls svg > use {
display: none;
}
.tui-image-editor-container .tui-image-editor-help-menu .enabled svg:hover > use.hover,
.tui-image-editor-container .tui-image-editor-controls .enabled svg:hover > use.hover,
.tui-image-editor-container .tui-image-editor-help-menu .normal svg:hover > use.hover,
.tui-image-editor-container .tui-image-editor-controls .normal svg:hover > use.hover {
.tui-image-editor-container
.tui-image-editor-help-menu
.enabled
svg:hover
> use.hover,
.tui-image-editor-container
.tui-image-editor-controls
.enabled
svg:hover
> use.hover,
.tui-image-editor-container
.tui-image-editor-help-menu
.normal
svg:hover
> use.hover,
.tui-image-editor-container
.tui-image-editor-controls
.normal
svg:hover
> use.hover {
display: block;
}
.tui-image-editor-container .tui-image-editor-help-menu .active svg:hover > use.hover,
.tui-image-editor-container .tui-image-editor-controls .active svg:hover > use.hover {
.tui-image-editor-container
.tui-image-editor-help-menu
.active
svg:hover
> use.hover,
.tui-image-editor-container
.tui-image-editor-controls
.active
svg:hover
> use.hover {
display: none;
}
.tui-image-editor-container .tui-image-editor-help-menu .on svg > use.hover,
@ -1569,28 +1704,76 @@ body > textarea {
.tui-image-editor-container .tui-image-editor-controls svg > use.normal {
display: block;
}
.tui-image-editor-container .tui-image-editor-help-menu .active svg > use.active,
.tui-image-editor-container .tui-image-editor-controls .active svg > use.active {
.tui-image-editor-container
.tui-image-editor-help-menu
.active
svg
> use.active,
.tui-image-editor-container
.tui-image-editor-controls
.active
svg
> use.active {
display: block;
}
.tui-image-editor-container .tui-image-editor-help-menu .enabled svg > use.enabled,
.tui-image-editor-container .tui-image-editor-controls .enabled svg > use.enabled {
.tui-image-editor-container
.tui-image-editor-help-menu
.enabled
svg
> use.enabled,
.tui-image-editor-container
.tui-image-editor-controls
.enabled
svg
> use.enabled {
display: block;
}
.tui-image-editor-container .tui-image-editor-help-menu .active svg > use.normal,
.tui-image-editor-container
.tui-image-editor-help-menu
.active
svg
> use.normal,
.tui-image-editor-container .tui-image-editor-controls .active svg > use.normal,
.tui-image-editor-container .tui-image-editor-help-menu .enabled svg > use.normal,
.tui-image-editor-container .tui-image-editor-controls .enabled svg > use.normal {
.tui-image-editor-container
.tui-image-editor-help-menu
.enabled
svg
> use.normal,
.tui-image-editor-container
.tui-image-editor-controls
.enabled
svg
> use.normal {
display: none;
}
.tui-image-editor-container .tui-image-editor-help-menu .help svg > use.disabled,
.tui-image-editor-container
.tui-image-editor-help-menu
.help
svg
> use.disabled,
.tui-image-editor-container .tui-image-editor-controls .help svg > use.disabled,
.tui-image-editor-container .tui-image-editor-help-menu .help.enabled svg > use.normal,
.tui-image-editor-container .tui-image-editor-controls .help.enabled svg > use.normal {
.tui-image-editor-container
.tui-image-editor-help-menu
.help.enabled
svg
> use.normal,
.tui-image-editor-container
.tui-image-editor-controls
.help.enabled
svg
> use.normal {
display: block;
}
.tui-image-editor-container .tui-image-editor-help-menu .help.enabled svg > use.disabled,
.tui-image-editor-container .tui-image-editor-controls .help.enabled svg > use.disabled {
.tui-image-editor-container
.tui-image-editor-help-menu
.help.enabled
svg
> use.disabled,
.tui-image-editor-container
.tui-image-editor-controls
.help.enabled
svg
> use.disabled {
display: none;
}
.tui-image-editor-container .tui-image-editor-controls:hover {
@ -1644,20 +1827,28 @@ body > textarea {
padding: 16px;
border-radius: 2px;
}
.tui-image-editor-container .color-picker-control .tui-colorpicker-palette-toggle-slider {
.tui-image-editor-container
.color-picker-control
.tui-colorpicker-palette-toggle-slider {
display: none;
}
.tui-image-editor-container .color-picker-control .tui-colorpicker-palette-button {
.tui-image-editor-container
.color-picker-control
.tui-colorpicker-palette-button {
border: 0;
border-radius: 100%;
margin: 2px;
background-size: cover;
font-size: 1px;
}
.tui-image-editor-container .color-picker-control .tui-colorpicker-palette-button[title="#ffffff"] {
.tui-image-editor-container
.color-picker-control
.tui-colorpicker-palette-button[title="#ffffff"] {
border: 1px solid #ccc;
}
.tui-image-editor-container .color-picker-control .tui-colorpicker-palette-button[title=""] {
.tui-image-editor-container
.color-picker-control
.tui-colorpicker-palette-button[title=""] {
border: 1px solid #ccc;
}
.tui-image-editor-container .color-picker-control .triangle {
@ -1671,8 +1862,13 @@ body > textarea {
left: 84px;
}
.tui-image-editor-container .color-picker-control .tui-colorpicker-container,
.tui-image-editor-container .color-picker-control .tui-colorpicker-palette-container ul,
.tui-image-editor-container .color-picker-control .tui-colorpicker-palette-container {
.tui-image-editor-container
.color-picker-control
.tui-colorpicker-palette-container
ul,
.tui-image-editor-container
.color-picker-control
.tui-colorpicker-palette-container {
width: 100%;
height: auto;
}
@ -1684,8 +1880,15 @@ body > textarea {
.tui-image-editor-container .filter-color-item .tui-image-editor-checkbox {
margin-top: 0;
}
.tui-image-editor-container .filter-color-item .tui-image-editor-checkbox input + label:before,
.tui-image-editor-container .filter-color-item .tui-image-editor-checkbox > label:before {
.tui-image-editor-container
.filter-color-item
.tui-image-editor-checkbox
input
+ label:before,
.tui-image-editor-container
.filter-color-item
.tui-image-editor-checkbox
> label:before {
left: -16px;
}
.tui-image-editor-container .color-picker {
@ -1730,7 +1933,10 @@ body > textarea {
.tui-image-editor-button[data-icontype="icon-polygon"]
svg
> use.active,
.tie-icon-add-button.icon-star .tui-image-editor-button[data-icontype="icon-star"] svg > use.active,
.tie-icon-add-button.icon-star
.tui-image-editor-button[data-icontype="icon-star"]
svg
> use.active,
.tie-icon-add-button.icon-star-2
.tui-image-editor-button[data-icontype="icon-star-2"]
svg
@ -1749,12 +1955,24 @@ body > textarea {
> use.active {
display: block;
}
.tie-draw-line-select-button.line .tui-image-editor-button.line svg > use.normal,
.tie-draw-line-select-button.free .tui-image-editor-button.free svg > use.normal {
.tie-draw-line-select-button.line
.tui-image-editor-button.line
svg
> use.normal,
.tie-draw-line-select-button.free
.tui-image-editor-button.free
svg
> use.normal {
display: none;
}
.tie-draw-line-select-button.line .tui-image-editor-button.line svg > use.active,
.tie-draw-line-select-button.free .tui-image-editor-button.free svg > use.active {
.tie-draw-line-select-button.line
.tui-image-editor-button.line
svg
> use.active,
.tie-draw-line-select-button.free
.tui-image-editor-button.free
svg
> use.active {
display: block;
}
.tie-flip-button.resetFlip .tui-image-editor-button.resetFlip svg > use.normal,
@ -1778,7 +1996,10 @@ body > textarea {
margin-right: 24px;
}
.tie-crop-button .tui-image-editor-button.preset.active svg > use.active,
.tie-crop-preset-button .tui-image-editor-button.preset.active svg > use.active {
.tie-crop-preset-button
.tui-image-editor-button.preset.active
svg
> use.active {
display: block;
}
.tie-crop-button .tui-image-editor-button.apply.active svg > use.active,
@ -1790,11 +2011,17 @@ body > textarea {
margin-right: 24px;
}
.tie-resize-button .tui-image-editor-button.preset.active svg > use.active,
.tie-resize-preset-button .tui-image-editor-button.preset.active svg > use.active {
.tie-resize-preset-button
.tui-image-editor-button.preset.active
svg
> use.active {
display: block;
}
.tie-resize-button .tui-image-editor-button.apply.active svg > use.active,
.tie-resize-preset-button .tui-image-editor-button.apply.active svg > use.active {
.tie-resize-preset-button
.tui-image-editor-button.apply.active
svg
> use.active {
display: block;
}
.tie-shape-button.rect .tui-image-editor-button.rect svg > use.normal,
@ -1810,9 +2037,18 @@ body > textarea {
.tie-text-effect-button .tui-image-editor-button.active svg > use.active {
display: block;
}
.tie-text-align-button.tie-text-align-left .tui-image-editor-button.left svg > use.active,
.tie-text-align-button.tie-text-align-center .tui-image-editor-button.center svg > use.active,
.tie-text-align-button.tie-text-align-right .tui-image-editor-button.right svg > use.active {
.tie-text-align-button.tie-text-align-left
.tui-image-editor-button.left
svg
> use.active,
.tie-text-align-button.tie-text-align-center
.tui-image-editor-button.center
svg
> use.active,
.tie-text-align-button.tie-text-align-right
.tui-image-editor-button.right
svg
> use.active {
display: block;
}
.tie-mask-image-file,
@ -1836,9 +2072,12 @@ body > textarea {
.tie-zoom-button.flipY .tui-image-editor-button.flipY svg > use.active {
display: block;
}
.tui-image-editor-container.top.tui-image-editor-top-optimization .tui-image-editor-controls ul {
.tui-image-editor-container.top.tui-image-editor-top-optimization
.tui-image-editor-controls
ul {
text-align: right;
}
.tui-image-editor-container.top.tui-image-editor-top-optimization .tui-image-editor-controls-logo {
.tui-image-editor-container.top.tui-image-editor-top-optimization
.tui-image-editor-controls-logo {
display: none;
}

@ -13,7 +13,9 @@ export default defineConfig(({ mode }) => {
return {
define: {
BUILD_MODE: production ? JSON.stringify("prod") : JSON.stringify("dev"),
BACKEND_URL: production ? JSON.stringify("") : JSON.stringify("http://localhost:7860/")
BACKEND_URL: production
? JSON.stringify("")
: JSON.stringify("http://localhost:7860/")
},
plugins: [
svelte({

1966
ui/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

@ -11,7 +11,7 @@
"importsNotUsedAsValues": "error",
"isolatedModules": true,
"resolveJsonModule": true,
"strict": true,
"strict": true,
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true,
@ -19,8 +19,8 @@
"baseUrl": ".",
"allowJs": true,
"checkJs": true,
"outDir": "dist"
"outDir": "dist"
},
"exclude": ["**/dist/**/*", "**/public/**/*", "**/*.config.js", "dist"],
"include": ["**/*.d.ts", "**/*.js", "**/*.ts", "**/*.svelte"],
}
"exclude": ["**/dist/**/*", "**/public/**/*", "**/*.config.js", "dist"],
"include": ["**/*.d.ts", "**/*.js", "**/*.ts", "**/*.svelte"]
}