docs: update refs, update script
This commit is contained in:
@@ -1 +1,10 @@
|
|||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
|
# Reference source (legacy Next.js design in refs/): branding icons are not needed
|
||||||
|
refs/public/icon.svg
|
||||||
|
refs/public/icon-dark-32x32.png
|
||||||
|
refs/public/icon-light-32x32.png
|
||||||
|
refs/public/apple-icon.png
|
||||||
|
refs/public/placeholder-logo.svg
|
||||||
|
refs/public/placeholder-logo.png
|
||||||
|
refs/public/placeholder.svg
|
||||||
|
|||||||
+2
-1
@@ -7,7 +7,8 @@
|
|||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"dev": "pnpm --dir web dev",
|
"dev": "pnpm --dir web dev",
|
||||||
"build": "pnpm --dir web build",
|
"build": "pnpm --dir web build",
|
||||||
"format": "pnpm --dir web format"
|
"format": "pnpm --dir web format",
|
||||||
|
"html": "pnpm --dir refs build && node scripts/extract-static.mjs refs/.next/server/app refs-html"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Ku6epXBOCTuK",
|
"author": "Ku6epXBOCTuK",
|
||||||
|
|||||||
@@ -7,11 +7,6 @@
|
|||||||
@layer properties {
|
@layer properties {
|
||||||
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
||||||
*,:before,:after,::backdrop {
|
*,:before,:after,::backdrop {
|
||||||
--tw-rotate-x:initial;
|
|
||||||
--tw-rotate-y:initial;
|
|
||||||
--tw-rotate-z:initial;
|
|
||||||
--tw-skew-x:initial;
|
|
||||||
--tw-skew-y:initial;
|
|
||||||
--tw-border-style:solid;
|
--tw-border-style:solid;
|
||||||
--tw-font-weight:initial;
|
--tw-font-weight:initial;
|
||||||
--tw-shadow:0 0 #0000;
|
--tw-shadow:0 0 #0000;
|
||||||
@@ -290,12 +285,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
}
|
}
|
||||||
@layer components;
|
@layer components;
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
.static {
|
|
||||||
position:static
|
|
||||||
}
|
|
||||||
.inline {
|
|
||||||
display:inline
|
|
||||||
}
|
|
||||||
.inline-flex {
|
.inline-flex {
|
||||||
display:inline-flex
|
display:inline-flex
|
||||||
}
|
}
|
||||||
@@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
.shrink-0 {
|
.shrink-0 {
|
||||||
flex-shrink:0
|
flex-shrink:0
|
||||||
}
|
}
|
||||||
.transform {
|
|
||||||
transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)
|
|
||||||
}
|
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items:center
|
align-items:center
|
||||||
}
|
}
|
||||||
@@ -630,7 +616,7 @@ button {
|
|||||||
--line:#33414c;
|
--line:#33414c;
|
||||||
--muted:#91a0ac;
|
--muted:#91a0ac;
|
||||||
--blue:#54a2ff;
|
--blue:#54a2ff;
|
||||||
background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px)
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
||||||
align-items:center;
|
align-items:center;
|
||||||
@@ -643,6 +629,26 @@ button {
|
|||||||
height:64px;
|
height:64px;
|
||||||
padding:0 clamp(20px,4vw,64px)
|
padding:0 clamp(20px,4vw,64px)
|
||||||
}
|
}
|
||||||
|
.topbar>.brand {
|
||||||
|
color:var(--foreground);
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
align-items:center;
|
||||||
|
gap:22px;
|
||||||
|
margin-left:auto;
|
||||||
|
margin-right:28px;
|
||||||
|
display:flex
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
color:var(--muted);
|
||||||
|
font:10px var(--font-mono);
|
||||||
|
white-space:nowrap;
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav a:hover,.top-nav a.active {
|
||||||
|
color:var(--blue)
|
||||||
|
}
|
||||||
.brand {
|
.brand {
|
||||||
font:600 14px var(--font-mono);
|
font:600 14px var(--font-mono);
|
||||||
gap:10px
|
gap:10px
|
||||||
@@ -1103,6 +1109,9 @@ h1 {
|
|||||||
gap:32px
|
gap:32px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.dark-mode .app-shell {
|
||||||
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.dark-mode .tile-canvas {
|
.dark-mode .tile-canvas {
|
||||||
background-color:#202a31;
|
background-color:#202a31;
|
||||||
@@ -1113,7 +1122,22 @@ h1 {
|
|||||||
}
|
}
|
||||||
@media (max-width:800px) {
|
@media (max-width:800px) {
|
||||||
.topbar {
|
.topbar {
|
||||||
padding:0 16px
|
flex-wrap:wrap;
|
||||||
|
gap:12px;
|
||||||
|
height:auto;
|
||||||
|
min-height:64px;
|
||||||
|
padding:12px 16px
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
order:3;
|
||||||
|
gap:12px;
|
||||||
|
width:100%;
|
||||||
|
margin:0;
|
||||||
|
padding-bottom:2px;
|
||||||
|
overflow:auto
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
font-size:9px
|
||||||
}
|
}
|
||||||
.status {
|
.status {
|
||||||
display:none
|
display:none
|
||||||
@@ -1532,9 +1556,9 @@ h1 {
|
|||||||
}
|
}
|
||||||
.catalog-page {
|
.catalog-page {
|
||||||
width:100%;
|
width:100%;
|
||||||
max-width:1680px;
|
max-width:none;
|
||||||
margin:0 auto;
|
margin:0;
|
||||||
padding:64px clamp(24px,4vw,72px) 72px
|
padding:60px clamp(24px,4vw,72px) 72px
|
||||||
}
|
}
|
||||||
.catalog-head {
|
.catalog-head {
|
||||||
border-bottom:1px solid var(--line);
|
border-bottom:1px solid var(--line);
|
||||||
@@ -1803,26 +1827,6 @@ h1 {
|
|||||||
gap:12px 18px
|
gap:12px 18px
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
@property --tw-rotate-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-z {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
}
|
||||||
@property --tw-border-style {
|
@property --tw-border-style {
|
||||||
syntax:"*";
|
syntax:"*";
|
||||||
@@ -1984,43 +1988,57 @@ h1 {
|
|||||||
<!--$-->
|
<!--$-->
|
||||||
<!--/$-->
|
<!--/$-->
|
||||||
</div>
|
</div>
|
||||||
<main class="app-shell dark-mode">
|
<main class="app-shell">
|
||||||
<header class="topbar">
|
<header class="topbar">
|
||||||
<div class="brand">
|
<a class="brand" href="/">
|
||||||
<span class="brand-mark">EP
|
<span class="brand-mark">EP
|
||||||
</span>
|
</span>
|
||||||
<span>easy-png-tools
|
<span>easy-png-tools
|
||||||
</span>
|
</span>
|
||||||
<span class="version">/ BACKGROUND REMOVER
|
<span class="version">/
|
||||||
|
<!-- -->BACKGROUND REMOVER
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</a>
|
||||||
|
<nav class="top-nav" aria-label="Primary navigation">
|
||||||
|
<a class="" href="/">Workspace
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/list-tools">Catalog
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/gradient">Gradient
|
||||||
|
</a>
|
||||||
|
<a class="active" href="/easy-png-tools/background-remover">Background remover
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
<div class="top-actions">
|
<div class="top-actions">
|
||||||
<span class="status">
|
<span class="status">
|
||||||
<i>
|
<i>
|
||||||
</i> AUTO PROCESSING
|
</i>
|
||||||
|
<!-- -->AUTO PROCESSING
|
||||||
</span>
|
</span>
|
||||||
<button class="icon-btn" aria-label="Toggle theme">
|
<button class="icon-btn" aria-label="Help">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sun" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-question-mark" aria-hidden="true">
|
||||||
<circle cx="12" cy="12" r="4">
|
<circle cx="12" cy="12" r="10">
|
||||||
</circle>
|
</circle>
|
||||||
<path d="M12 2v2">
|
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3">
|
||||||
</path>
|
</path>
|
||||||
<path d="M12 20v2">
|
<path d="M12 17h.01">
|
||||||
</path>
|
|
||||||
<path d="m4.93 4.93 1.41 1.41">
|
|
||||||
</path>
|
|
||||||
<path d="m17.66 17.66 1.41 1.41">
|
|
||||||
</path>
|
|
||||||
<path d="M2 12h2">
|
|
||||||
</path>
|
|
||||||
<path d="M20 12h2">
|
|
||||||
</path>
|
|
||||||
<path d="m6.34 17.66-1.41 1.41">
|
|
||||||
</path>
|
|
||||||
<path d="m19.07 4.93-1.41 1.41">
|
|
||||||
</path>
|
</path>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="icon-btn" aria-label="Toggle theme">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-moon" aria-hidden="true">
|
||||||
|
<path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div class="language">
|
||||||
|
<button class="active">RU
|
||||||
|
</button>
|
||||||
|
<span>/
|
||||||
|
</span>
|
||||||
|
<button>EN
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="tool-page">
|
<div class="tool-page">
|
||||||
|
|||||||
+62
-44
@@ -7,11 +7,6 @@
|
|||||||
@layer properties {
|
@layer properties {
|
||||||
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
||||||
*,:before,:after,::backdrop {
|
*,:before,:after,::backdrop {
|
||||||
--tw-rotate-x:initial;
|
|
||||||
--tw-rotate-y:initial;
|
|
||||||
--tw-rotate-z:initial;
|
|
||||||
--tw-skew-x:initial;
|
|
||||||
--tw-skew-y:initial;
|
|
||||||
--tw-border-style:solid;
|
--tw-border-style:solid;
|
||||||
--tw-font-weight:initial;
|
--tw-font-weight:initial;
|
||||||
--tw-shadow:0 0 #0000;
|
--tw-shadow:0 0 #0000;
|
||||||
@@ -290,12 +285,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
}
|
}
|
||||||
@layer components;
|
@layer components;
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
.static {
|
|
||||||
position:static
|
|
||||||
}
|
|
||||||
.inline {
|
|
||||||
display:inline
|
|
||||||
}
|
|
||||||
.inline-flex {
|
.inline-flex {
|
||||||
display:inline-flex
|
display:inline-flex
|
||||||
}
|
}
|
||||||
@@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
.shrink-0 {
|
.shrink-0 {
|
||||||
flex-shrink:0
|
flex-shrink:0
|
||||||
}
|
}
|
||||||
.transform {
|
|
||||||
transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)
|
|
||||||
}
|
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items:center
|
align-items:center
|
||||||
}
|
}
|
||||||
@@ -630,7 +616,7 @@ button {
|
|||||||
--line:#33414c;
|
--line:#33414c;
|
||||||
--muted:#91a0ac;
|
--muted:#91a0ac;
|
||||||
--blue:#54a2ff;
|
--blue:#54a2ff;
|
||||||
background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px)
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
||||||
align-items:center;
|
align-items:center;
|
||||||
@@ -643,6 +629,26 @@ button {
|
|||||||
height:64px;
|
height:64px;
|
||||||
padding:0 clamp(20px,4vw,64px)
|
padding:0 clamp(20px,4vw,64px)
|
||||||
}
|
}
|
||||||
|
.topbar>.brand {
|
||||||
|
color:var(--foreground);
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
align-items:center;
|
||||||
|
gap:22px;
|
||||||
|
margin-left:auto;
|
||||||
|
margin-right:28px;
|
||||||
|
display:flex
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
color:var(--muted);
|
||||||
|
font:10px var(--font-mono);
|
||||||
|
white-space:nowrap;
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav a:hover,.top-nav a.active {
|
||||||
|
color:var(--blue)
|
||||||
|
}
|
||||||
.brand {
|
.brand {
|
||||||
font:600 14px var(--font-mono);
|
font:600 14px var(--font-mono);
|
||||||
gap:10px
|
gap:10px
|
||||||
@@ -1103,6 +1109,9 @@ h1 {
|
|||||||
gap:32px
|
gap:32px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.dark-mode .app-shell {
|
||||||
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.dark-mode .tile-canvas {
|
.dark-mode .tile-canvas {
|
||||||
background-color:#202a31;
|
background-color:#202a31;
|
||||||
@@ -1113,7 +1122,22 @@ h1 {
|
|||||||
}
|
}
|
||||||
@media (max-width:800px) {
|
@media (max-width:800px) {
|
||||||
.topbar {
|
.topbar {
|
||||||
padding:0 16px
|
flex-wrap:wrap;
|
||||||
|
gap:12px;
|
||||||
|
height:auto;
|
||||||
|
min-height:64px;
|
||||||
|
padding:12px 16px
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
order:3;
|
||||||
|
gap:12px;
|
||||||
|
width:100%;
|
||||||
|
margin:0;
|
||||||
|
padding-bottom:2px;
|
||||||
|
overflow:auto
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
font-size:9px
|
||||||
}
|
}
|
||||||
.status {
|
.status {
|
||||||
display:none
|
display:none
|
||||||
@@ -1532,9 +1556,9 @@ h1 {
|
|||||||
}
|
}
|
||||||
.catalog-page {
|
.catalog-page {
|
||||||
width:100%;
|
width:100%;
|
||||||
max-width:1680px;
|
max-width:none;
|
||||||
margin:0 auto;
|
margin:0;
|
||||||
padding:64px clamp(24px,4vw,72px) 72px
|
padding:60px clamp(24px,4vw,72px) 72px
|
||||||
}
|
}
|
||||||
.catalog-head {
|
.catalog-head {
|
||||||
border-bottom:1px solid var(--line);
|
border-bottom:1px solid var(--line);
|
||||||
@@ -1803,26 +1827,6 @@ h1 {
|
|||||||
gap:12px 18px
|
gap:12px 18px
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
@property --tw-rotate-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-z {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
}
|
||||||
@property --tw-border-style {
|
@property --tw-border-style {
|
||||||
syntax:"*";
|
syntax:"*";
|
||||||
@@ -1986,18 +1990,30 @@ h1 {
|
|||||||
</div>
|
</div>
|
||||||
<main class="app-shell">
|
<main class="app-shell">
|
||||||
<header class="topbar">
|
<header class="topbar">
|
||||||
<div class="brand">
|
<a class="brand" href="/">
|
||||||
<span class="brand-mark">EP
|
<span class="brand-mark">EP
|
||||||
</span>
|
</span>
|
||||||
<span>easy-png-tools
|
<span>easy-png-tools
|
||||||
</span>
|
</span>
|
||||||
<span class="version">/ DEMO
|
<span class="version">/
|
||||||
|
<!-- -->WORKSPACE
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</a>
|
||||||
|
<nav class="top-nav" aria-label="Primary navigation">
|
||||||
|
<a class="" href="/">Workspace
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/list-tools">Catalog
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/gradient">Gradient
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/background-remover">Background remover
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
<div class="top-actions">
|
<div class="top-actions">
|
||||||
<span class="status">
|
<span class="status">
|
||||||
<i>
|
<i>
|
||||||
</i> AUTO PIPELINE
|
</i>
|
||||||
|
<!-- -->AUTO PIPELINE
|
||||||
</span>
|
</span>
|
||||||
<button class="icon-btn" aria-label="Help">
|
<button class="icon-btn" aria-label="Help">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-question-mark" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-question-mark" aria-hidden="true">
|
||||||
@@ -2018,7 +2034,9 @@ h1 {
|
|||||||
<div class="language">
|
<div class="language">
|
||||||
<button class="active">RU
|
<button class="active">RU
|
||||||
</button>
|
</button>
|
||||||
<button class="">EN
|
<span>/
|
||||||
|
</span>
|
||||||
|
<button>EN
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+82
-60
@@ -7,11 +7,6 @@
|
|||||||
@layer properties {
|
@layer properties {
|
||||||
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
||||||
*,:before,:after,::backdrop {
|
*,:before,:after,::backdrop {
|
||||||
--tw-rotate-x:initial;
|
|
||||||
--tw-rotate-y:initial;
|
|
||||||
--tw-rotate-z:initial;
|
|
||||||
--tw-skew-x:initial;
|
|
||||||
--tw-skew-y:initial;
|
|
||||||
--tw-border-style:solid;
|
--tw-border-style:solid;
|
||||||
--tw-font-weight:initial;
|
--tw-font-weight:initial;
|
||||||
--tw-shadow:0 0 #0000;
|
--tw-shadow:0 0 #0000;
|
||||||
@@ -290,12 +285,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
}
|
}
|
||||||
@layer components;
|
@layer components;
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
.static {
|
|
||||||
position:static
|
|
||||||
}
|
|
||||||
.inline {
|
|
||||||
display:inline
|
|
||||||
}
|
|
||||||
.inline-flex {
|
.inline-flex {
|
||||||
display:inline-flex
|
display:inline-flex
|
||||||
}
|
}
|
||||||
@@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
.shrink-0 {
|
.shrink-0 {
|
||||||
flex-shrink:0
|
flex-shrink:0
|
||||||
}
|
}
|
||||||
.transform {
|
|
||||||
transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)
|
|
||||||
}
|
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items:center
|
align-items:center
|
||||||
}
|
}
|
||||||
@@ -630,7 +616,7 @@ button {
|
|||||||
--line:#33414c;
|
--line:#33414c;
|
||||||
--muted:#91a0ac;
|
--muted:#91a0ac;
|
||||||
--blue:#54a2ff;
|
--blue:#54a2ff;
|
||||||
background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px)
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
||||||
align-items:center;
|
align-items:center;
|
||||||
@@ -643,6 +629,26 @@ button {
|
|||||||
height:64px;
|
height:64px;
|
||||||
padding:0 clamp(20px,4vw,64px)
|
padding:0 clamp(20px,4vw,64px)
|
||||||
}
|
}
|
||||||
|
.topbar>.brand {
|
||||||
|
color:var(--foreground);
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
align-items:center;
|
||||||
|
gap:22px;
|
||||||
|
margin-left:auto;
|
||||||
|
margin-right:28px;
|
||||||
|
display:flex
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
color:var(--muted);
|
||||||
|
font:10px var(--font-mono);
|
||||||
|
white-space:nowrap;
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav a:hover,.top-nav a.active {
|
||||||
|
color:var(--blue)
|
||||||
|
}
|
||||||
.brand {
|
.brand {
|
||||||
font:600 14px var(--font-mono);
|
font:600 14px var(--font-mono);
|
||||||
gap:10px
|
gap:10px
|
||||||
@@ -1103,6 +1109,9 @@ h1 {
|
|||||||
gap:32px
|
gap:32px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.dark-mode .app-shell {
|
||||||
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.dark-mode .tile-canvas {
|
.dark-mode .tile-canvas {
|
||||||
background-color:#202a31;
|
background-color:#202a31;
|
||||||
@@ -1113,7 +1122,22 @@ h1 {
|
|||||||
}
|
}
|
||||||
@media (max-width:800px) {
|
@media (max-width:800px) {
|
||||||
.topbar {
|
.topbar {
|
||||||
padding:0 16px
|
flex-wrap:wrap;
|
||||||
|
gap:12px;
|
||||||
|
height:auto;
|
||||||
|
min-height:64px;
|
||||||
|
padding:12px 16px
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
order:3;
|
||||||
|
gap:12px;
|
||||||
|
width:100%;
|
||||||
|
margin:0;
|
||||||
|
padding-bottom:2px;
|
||||||
|
overflow:auto
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
font-size:9px
|
||||||
}
|
}
|
||||||
.status {
|
.status {
|
||||||
display:none
|
display:none
|
||||||
@@ -1532,9 +1556,9 @@ h1 {
|
|||||||
}
|
}
|
||||||
.catalog-page {
|
.catalog-page {
|
||||||
width:100%;
|
width:100%;
|
||||||
max-width:1680px;
|
max-width:none;
|
||||||
margin:0 auto;
|
margin:0;
|
||||||
padding:64px clamp(24px,4vw,72px) 72px
|
padding:60px clamp(24px,4vw,72px) 72px
|
||||||
}
|
}
|
||||||
.catalog-head {
|
.catalog-head {
|
||||||
border-bottom:1px solid var(--line);
|
border-bottom:1px solid var(--line);
|
||||||
@@ -1803,26 +1827,6 @@ h1 {
|
|||||||
gap:12px 18px
|
gap:12px 18px
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
@property --tw-rotate-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-z {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
}
|
||||||
@property --tw-border-style {
|
@property --tw-border-style {
|
||||||
syntax:"*";
|
syntax:"*";
|
||||||
@@ -1984,39 +1988,57 @@ h1 {
|
|||||||
<!--$-->
|
<!--$-->
|
||||||
<!--/$-->
|
<!--/$-->
|
||||||
</div>
|
</div>
|
||||||
<main class="app-shell dark-mode">
|
<main class="app-shell">
|
||||||
<header class="topbar">
|
<header class="topbar">
|
||||||
<div class="brand">
|
<a class="brand" href="/">
|
||||||
<span class="brand-mark">EP
|
<span class="brand-mark">EP
|
||||||
</span>
|
</span>
|
||||||
<span>easy-png-tools
|
<span>easy-png-tools
|
||||||
</span>
|
</span>
|
||||||
<span class="version">/ GRADIENT
|
<span class="version">/
|
||||||
|
<!-- -->GRADIENT
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</a>
|
||||||
|
<nav class="top-nav" aria-label="Primary navigation">
|
||||||
|
<a class="" href="/">Workspace
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/list-tools">Catalog
|
||||||
|
</a>
|
||||||
|
<a class="active" href="/easy-png-tools/gradient">Gradient
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/background-remover">Background remover
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
<div class="top-actions">
|
<div class="top-actions">
|
||||||
<button class="icon-btn" aria-label="Toggle theme">
|
<span class="status">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sun" aria-hidden="true">
|
<i>
|
||||||
<circle cx="12" cy="12" r="4">
|
</i>
|
||||||
|
<!-- -->LIVE PREVIEW
|
||||||
|
</span>
|
||||||
|
<button class="icon-btn" aria-label="Help">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-question-mark" aria-hidden="true">
|
||||||
|
<circle cx="12" cy="12" r="10">
|
||||||
</circle>
|
</circle>
|
||||||
<path d="M12 2v2">
|
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3">
|
||||||
</path>
|
</path>
|
||||||
<path d="M12 20v2">
|
<path d="M12 17h.01">
|
||||||
</path>
|
|
||||||
<path d="m4.93 4.93 1.41 1.41">
|
|
||||||
</path>
|
|
||||||
<path d="m17.66 17.66 1.41 1.41">
|
|
||||||
</path>
|
|
||||||
<path d="M2 12h2">
|
|
||||||
</path>
|
|
||||||
<path d="M20 12h2">
|
|
||||||
</path>
|
|
||||||
<path d="m6.34 17.66-1.41 1.41">
|
|
||||||
</path>
|
|
||||||
<path d="m19.07 4.93-1.41 1.41">
|
|
||||||
</path>
|
</path>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="icon-btn" aria-label="Toggle theme">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-moon" aria-hidden="true">
|
||||||
|
<path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div class="language">
|
||||||
|
<button class="active">RU
|
||||||
|
</button>
|
||||||
|
<span>/
|
||||||
|
</span>
|
||||||
|
<button>EN
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="tool-page">
|
<div class="tool-page">
|
||||||
|
|||||||
+62
-44
@@ -7,11 +7,6 @@
|
|||||||
@layer properties {
|
@layer properties {
|
||||||
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
||||||
*,:before,:after,::backdrop {
|
*,:before,:after,::backdrop {
|
||||||
--tw-rotate-x:initial;
|
|
||||||
--tw-rotate-y:initial;
|
|
||||||
--tw-rotate-z:initial;
|
|
||||||
--tw-skew-x:initial;
|
|
||||||
--tw-skew-y:initial;
|
|
||||||
--tw-border-style:solid;
|
--tw-border-style:solid;
|
||||||
--tw-font-weight:initial;
|
--tw-font-weight:initial;
|
||||||
--tw-shadow:0 0 #0000;
|
--tw-shadow:0 0 #0000;
|
||||||
@@ -290,12 +285,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
}
|
}
|
||||||
@layer components;
|
@layer components;
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
.static {
|
|
||||||
position:static
|
|
||||||
}
|
|
||||||
.inline {
|
|
||||||
display:inline
|
|
||||||
}
|
|
||||||
.inline-flex {
|
.inline-flex {
|
||||||
display:inline-flex
|
display:inline-flex
|
||||||
}
|
}
|
||||||
@@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
.shrink-0 {
|
.shrink-0 {
|
||||||
flex-shrink:0
|
flex-shrink:0
|
||||||
}
|
}
|
||||||
.transform {
|
|
||||||
transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)
|
|
||||||
}
|
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items:center
|
align-items:center
|
||||||
}
|
}
|
||||||
@@ -630,7 +616,7 @@ button {
|
|||||||
--line:#33414c;
|
--line:#33414c;
|
||||||
--muted:#91a0ac;
|
--muted:#91a0ac;
|
||||||
--blue:#54a2ff;
|
--blue:#54a2ff;
|
||||||
background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px)
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
||||||
align-items:center;
|
align-items:center;
|
||||||
@@ -643,6 +629,26 @@ button {
|
|||||||
height:64px;
|
height:64px;
|
||||||
padding:0 clamp(20px,4vw,64px)
|
padding:0 clamp(20px,4vw,64px)
|
||||||
}
|
}
|
||||||
|
.topbar>.brand {
|
||||||
|
color:var(--foreground);
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
align-items:center;
|
||||||
|
gap:22px;
|
||||||
|
margin-left:auto;
|
||||||
|
margin-right:28px;
|
||||||
|
display:flex
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
color:var(--muted);
|
||||||
|
font:10px var(--font-mono);
|
||||||
|
white-space:nowrap;
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav a:hover,.top-nav a.active {
|
||||||
|
color:var(--blue)
|
||||||
|
}
|
||||||
.brand {
|
.brand {
|
||||||
font:600 14px var(--font-mono);
|
font:600 14px var(--font-mono);
|
||||||
gap:10px
|
gap:10px
|
||||||
@@ -1103,6 +1109,9 @@ h1 {
|
|||||||
gap:32px
|
gap:32px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.dark-mode .app-shell {
|
||||||
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.dark-mode .tile-canvas {
|
.dark-mode .tile-canvas {
|
||||||
background-color:#202a31;
|
background-color:#202a31;
|
||||||
@@ -1113,7 +1122,22 @@ h1 {
|
|||||||
}
|
}
|
||||||
@media (max-width:800px) {
|
@media (max-width:800px) {
|
||||||
.topbar {
|
.topbar {
|
||||||
padding:0 16px
|
flex-wrap:wrap;
|
||||||
|
gap:12px;
|
||||||
|
height:auto;
|
||||||
|
min-height:64px;
|
||||||
|
padding:12px 16px
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
order:3;
|
||||||
|
gap:12px;
|
||||||
|
width:100%;
|
||||||
|
margin:0;
|
||||||
|
padding-bottom:2px;
|
||||||
|
overflow:auto
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
font-size:9px
|
||||||
}
|
}
|
||||||
.status {
|
.status {
|
||||||
display:none
|
display:none
|
||||||
@@ -1532,9 +1556,9 @@ h1 {
|
|||||||
}
|
}
|
||||||
.catalog-page {
|
.catalog-page {
|
||||||
width:100%;
|
width:100%;
|
||||||
max-width:1680px;
|
max-width:none;
|
||||||
margin:0 auto;
|
margin:0;
|
||||||
padding:64px clamp(24px,4vw,72px) 72px
|
padding:60px clamp(24px,4vw,72px) 72px
|
||||||
}
|
}
|
||||||
.catalog-head {
|
.catalog-head {
|
||||||
border-bottom:1px solid var(--line);
|
border-bottom:1px solid var(--line);
|
||||||
@@ -1803,26 +1827,6 @@ h1 {
|
|||||||
gap:12px 18px
|
gap:12px 18px
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
@property --tw-rotate-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-z {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
}
|
||||||
@property --tw-border-style {
|
@property --tw-border-style {
|
||||||
syntax:"*";
|
syntax:"*";
|
||||||
@@ -1986,18 +1990,30 @@ h1 {
|
|||||||
</div>
|
</div>
|
||||||
<main class="app-shell">
|
<main class="app-shell">
|
||||||
<header class="topbar">
|
<header class="topbar">
|
||||||
<div class="brand">
|
<a class="brand" href="/">
|
||||||
<span class="brand-mark">EP
|
<span class="brand-mark">EP
|
||||||
</span>
|
</span>
|
||||||
<span>easy-png-tools
|
<span>easy-png-tools
|
||||||
</span>
|
</span>
|
||||||
<span class="version">/ DEMO
|
<span class="version">/
|
||||||
|
<!-- -->WORKSPACE
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</a>
|
||||||
|
<nav class="top-nav" aria-label="Primary navigation">
|
||||||
|
<a class="active" href="/">Workspace
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/list-tools">Catalog
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/gradient">Gradient
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/background-remover">Background remover
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
<div class="top-actions">
|
<div class="top-actions">
|
||||||
<span class="status">
|
<span class="status">
|
||||||
<i>
|
<i>
|
||||||
</i> AUTO PIPELINE
|
</i>
|
||||||
|
<!-- -->AUTO PIPELINE
|
||||||
</span>
|
</span>
|
||||||
<button class="icon-btn" aria-label="Help">
|
<button class="icon-btn" aria-label="Help">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-question-mark" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-question-mark" aria-hidden="true">
|
||||||
@@ -2018,7 +2034,9 @@ h1 {
|
|||||||
<div class="language">
|
<div class="language">
|
||||||
<button class="active">RU
|
<button class="active">RU
|
||||||
</button>
|
</button>
|
||||||
<button class="">EN
|
<span>/
|
||||||
|
</span>
|
||||||
|
<button>EN
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+92
-46
@@ -7,11 +7,6 @@
|
|||||||
@layer properties {
|
@layer properties {
|
||||||
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
||||||
*,:before,:after,::backdrop {
|
*,:before,:after,::backdrop {
|
||||||
--tw-rotate-x:initial;
|
|
||||||
--tw-rotate-y:initial;
|
|
||||||
--tw-rotate-z:initial;
|
|
||||||
--tw-skew-x:initial;
|
|
||||||
--tw-skew-y:initial;
|
|
||||||
--tw-border-style:solid;
|
--tw-border-style:solid;
|
||||||
--tw-font-weight:initial;
|
--tw-font-weight:initial;
|
||||||
--tw-shadow:0 0 #0000;
|
--tw-shadow:0 0 #0000;
|
||||||
@@ -290,12 +285,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
}
|
}
|
||||||
@layer components;
|
@layer components;
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
.static {
|
|
||||||
position:static
|
|
||||||
}
|
|
||||||
.inline {
|
|
||||||
display:inline
|
|
||||||
}
|
|
||||||
.inline-flex {
|
.inline-flex {
|
||||||
display:inline-flex
|
display:inline-flex
|
||||||
}
|
}
|
||||||
@@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) {
|
|||||||
.shrink-0 {
|
.shrink-0 {
|
||||||
flex-shrink:0
|
flex-shrink:0
|
||||||
}
|
}
|
||||||
.transform {
|
|
||||||
transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)
|
|
||||||
}
|
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items:center
|
align-items:center
|
||||||
}
|
}
|
||||||
@@ -630,7 +616,7 @@ button {
|
|||||||
--line:#33414c;
|
--line:#33414c;
|
||||||
--muted:#91a0ac;
|
--muted:#91a0ac;
|
||||||
--blue:#54a2ff;
|
--blue:#54a2ff;
|
||||||
background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px)
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer {
|
||||||
align-items:center;
|
align-items:center;
|
||||||
@@ -643,6 +629,26 @@ button {
|
|||||||
height:64px;
|
height:64px;
|
||||||
padding:0 clamp(20px,4vw,64px)
|
padding:0 clamp(20px,4vw,64px)
|
||||||
}
|
}
|
||||||
|
.topbar>.brand {
|
||||||
|
color:var(--foreground);
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
align-items:center;
|
||||||
|
gap:22px;
|
||||||
|
margin-left:auto;
|
||||||
|
margin-right:28px;
|
||||||
|
display:flex
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
color:var(--muted);
|
||||||
|
font:10px var(--font-mono);
|
||||||
|
white-space:nowrap;
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.top-nav a:hover,.top-nav a.active {
|
||||||
|
color:var(--blue)
|
||||||
|
}
|
||||||
.brand {
|
.brand {
|
||||||
font:600 14px var(--font-mono);
|
font:600 14px var(--font-mono);
|
||||||
gap:10px
|
gap:10px
|
||||||
@@ -1103,6 +1109,9 @@ h1 {
|
|||||||
gap:32px
|
gap:32px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.dark-mode .app-shell {
|
||||||
|
background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px)
|
||||||
}
|
}
|
||||||
.dark-mode .tile-canvas {
|
.dark-mode .tile-canvas {
|
||||||
background-color:#202a31;
|
background-color:#202a31;
|
||||||
@@ -1113,7 +1122,22 @@ h1 {
|
|||||||
}
|
}
|
||||||
@media (max-width:800px) {
|
@media (max-width:800px) {
|
||||||
.topbar {
|
.topbar {
|
||||||
padding:0 16px
|
flex-wrap:wrap;
|
||||||
|
gap:12px;
|
||||||
|
height:auto;
|
||||||
|
min-height:64px;
|
||||||
|
padding:12px 16px
|
||||||
|
}
|
||||||
|
.top-nav {
|
||||||
|
order:3;
|
||||||
|
gap:12px;
|
||||||
|
width:100%;
|
||||||
|
margin:0;
|
||||||
|
padding-bottom:2px;
|
||||||
|
overflow:auto
|
||||||
|
}
|
||||||
|
.top-nav a {
|
||||||
|
font-size:9px
|
||||||
}
|
}
|
||||||
.status {
|
.status {
|
||||||
display:none
|
display:none
|
||||||
@@ -1532,9 +1556,9 @@ h1 {
|
|||||||
}
|
}
|
||||||
.catalog-page {
|
.catalog-page {
|
||||||
width:100%;
|
width:100%;
|
||||||
max-width:1680px;
|
max-width:none;
|
||||||
margin:0 auto;
|
margin:0;
|
||||||
padding:64px clamp(24px,4vw,72px) 72px
|
padding:60px clamp(24px,4vw,72px) 72px
|
||||||
}
|
}
|
||||||
.catalog-head {
|
.catalog-head {
|
||||||
border-bottom:1px solid var(--line);
|
border-bottom:1px solid var(--line);
|
||||||
@@ -1803,26 +1827,6 @@ h1 {
|
|||||||
gap:12px 18px
|
gap:12px 18px
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
@property --tw-rotate-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-rotate-z {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-x {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
|
||||||
@property --tw-skew-y {
|
|
||||||
syntax:"*";
|
|
||||||
inherits:false
|
|
||||||
}
|
}
|
||||||
@property --tw-border-style {
|
@property --tw-border-style {
|
||||||
syntax:"*";
|
syntax:"*";
|
||||||
@@ -1984,19 +1988,60 @@ h1 {
|
|||||||
<!--$-->
|
<!--$-->
|
||||||
<!--/$-->
|
<!--/$-->
|
||||||
</div>
|
</div>
|
||||||
<main class="catalog-page">
|
<main class="app-shell">
|
||||||
<header class="catalog-nav">
|
<header class="topbar">
|
||||||
<a class="catalog-brand" href="/">easy-png-tools
|
<a class="brand" href="/">
|
||||||
|
<span class="brand-mark">EP
|
||||||
|
</span>
|
||||||
|
<span>easy-png-tools
|
||||||
|
</span>
|
||||||
|
<span class="version">/
|
||||||
|
<!-- -->CATALOG
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<nav>
|
<nav class="top-nav" aria-label="Primary navigation">
|
||||||
<a href="/">Workspace
|
<a class="" href="/">Workspace
|
||||||
</a>
|
</a>
|
||||||
<a class="current" href="/easy-png-tools/list-tools">Catalog
|
<a class="active" href="/easy-png-tools/list-tools">Catalog
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/gradient">Gradient
|
||||||
|
</a>
|
||||||
|
<a class="" href="/easy-png-tools/background-remover">Background remover
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
<span class="catalog-nav-status">LOCAL MODE / READY
|
<div class="top-actions">
|
||||||
|
<span class="status">
|
||||||
|
<i>
|
||||||
|
</i>
|
||||||
|
<!-- -->LOCAL MODE / READY
|
||||||
</span>
|
</span>
|
||||||
|
<button class="icon-btn" aria-label="Help">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-question-mark" aria-hidden="true">
|
||||||
|
<circle cx="12" cy="12" r="10">
|
||||||
|
</circle>
|
||||||
|
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3">
|
||||||
|
</path>
|
||||||
|
<path d="M12 17h.01">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="icon-btn" aria-label="Toggle theme">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-moon" aria-hidden="true">
|
||||||
|
<path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div class="language">
|
||||||
|
<button class="active">RU
|
||||||
|
</button>
|
||||||
|
<span>/
|
||||||
|
</span>
|
||||||
|
<button>EN
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
<div class="catalog-page">
|
||||||
<div class="catalog-head">
|
<div class="catalog-head">
|
||||||
<div>
|
<div>
|
||||||
<div class="eyebrow">EASY-PNG-TOOLS / CATALOG
|
<div class="eyebrow">EASY-PNG-TOOLS / CATALOG
|
||||||
@@ -2901,6 +2946,7 @@ h1 {
|
|||||||
<span>•
|
<span>•
|
||||||
</span> YOUR FILES NEVER LEAVE THIS DEVICE
|
</span> YOUR FILES NEVER LEAVE THIS DEVICE
|
||||||
</footer>
|
</footer>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<!--$-->
|
<!--$-->
|
||||||
<!--/$-->
|
<!--/$-->
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import TopBar from '@/components/top-bar'
|
||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { Download, Moon, RotateCcw, Sun, Upload, Check } from 'lucide-react'
|
import { Download, RotateCcw, Upload, Check } from 'lucide-react'
|
||||||
|
|
||||||
export default function BackgroundRemoverPage() {
|
export default function BackgroundRemoverPage() {
|
||||||
const [color, setColor] = useState('#E8EEF2')
|
const [color, setColor] = useState('#E8EEF2')
|
||||||
const [similarity, setSimilarity] = useState(72)
|
const [similarity, setSimilarity] = useState(72)
|
||||||
const [outerOnly, setOuterOnly] = useState(true)
|
const [outerOnly, setOuterOnly] = useState(true)
|
||||||
const [showMask, setShowMask] = useState(false)
|
const [showMask, setShowMask] = useState(false)
|
||||||
const [dark, setDark] = useState(true)
|
|
||||||
const [downloaded, setDownloaded] = useState(false)
|
const [downloaded, setDownloaded] = useState(false)
|
||||||
const previewBackground = showMask ? 'repeating-conic-gradient(#7b8791 0 25%, #cbd3da 0 50%) 50% / 28px 28px' : 'repeating-conic-gradient(#d7dce0 0 25%, #f3f5f6 0 50%) 50% / 28px 28px'
|
const previewBackground = showMask ? 'repeating-conic-gradient(#7b8791 0 25%, #cbd3da 0 50%) 50% / 28px 28px' : 'repeating-conic-gradient(#d7dce0 0 25%, #f3f5f6 0 50%) 50% / 28px 28px'
|
||||||
const subjectStyle = useMemo(() => ({ background: showMask ? '#596773' : 'linear-gradient(145deg,#1769d2 0 38%,#00a8c7 38% 66%,#bd7411 66%)', opacity: showMask ? .88 : 1, clipPath: `polygon(23% 11%, 73% 8%, 89% 30%, 79% 81%, 52% 93%, 17% 78%, 8% 39%)` }), [showMask])
|
const subjectStyle = useMemo(() => ({ background: showMask ? '#596773' : 'linear-gradient(145deg,#1769d2 0 38%,#00a8c7 38% 66%,#bd7411 66%)', opacity: showMask ? .88 : 1, clipPath: `polygon(23% 11%, 73% 8%, 89% 30%, 79% 81%, 52% 93%, 17% 78%, 8% 39%)` }), [showMask])
|
||||||
const reset = () => { setColor('#E8EEF2'); setSimilarity(72); setOuterOnly(true); setShowMask(false) }
|
const reset = () => { setColor('#E8EEF2'); setSimilarity(72); setOuterOnly(true); setShowMask(false) }
|
||||||
return <main className={`app-shell ${dark ? 'dark-mode' : ''}`}>
|
return <main className="app-shell">
|
||||||
<header className="topbar"><div className="brand"><span className="brand-mark">EP</span><span>easy-png-tools</span><span className="version">/ BACKGROUND REMOVER</span></div><div className="top-actions"><span className="status"><i /> AUTO PROCESSING</span><button className="icon-btn" aria-label="Toggle theme" onClick={() => setDark(!dark)}>{dark ? <Sun size={17} /> : <Moon size={17} />}</button></div></header>
|
<TopBar section="BACKGROUND REMOVER" status="AUTO PROCESSING" />
|
||||||
<div className="tool-page"><div className="eyebrow">PNG PROCESSING <span>/</span> SINGLE TOOL</div><div className="tool-title"><div><h1>Remove background.</h1><p className="lede">Select a background color and tune the edge detection. Changes are processed automatically in your browser.</p></div><span className="tool-status"><i /> LIVE PREVIEW</span></div>
|
<div className="tool-page"><div className="eyebrow">PNG PROCESSING <span>/</span> SINGLE TOOL</div><div className="tool-title"><div><h1>Remove background.</h1><p className="lede">Select a background color and tune the edge detection. Changes are processed automatically in your browser.</p></div><span className="tool-status"><i /> LIVE PREVIEW</span></div>
|
||||||
<div className="remover-layout"><section className="settings-panel"><div className="panel-heading"><div><span className="label">REMOVER SETTINGS</span><strong>Configure detection</strong></div><span className="step-type">TOOL 02</span></div>
|
<div className="remover-layout"><section className="settings-panel"><div className="panel-heading"><div><span className="label">REMOVER SETTINGS</span><strong>Configure detection</strong></div><span className="step-type">TOOL 02</span></div>
|
||||||
<div className="setting-group"><label>BACKGROUND COLOR</label><div className="color-field"><span className="swatch" style={{ background: color }} /><input value={color} onChange={e => setColor(e.target.value)} /><input className="native-color" type="color" value={color} onChange={e => setColor(e.target.value)} aria-label="Choose background color" /></div><div className="color-reference"><span style={{ background: color }} /> sampled from image background</div></div>
|
<div className="setting-group"><label>BACKGROUND COLOR</label><div className="color-field"><span className="swatch" style={{ background: color }} /><input value={color} onChange={e => setColor(e.target.value)} /><input className="native-color" type="color" value={color} onChange={e => setColor(e.target.value)} aria-label="Choose background color" /></div><div className="color-reference"><span style={{ background: color }} /> sampled from image background</div></div>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import TopBar from '@/components/top-bar'
|
||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { Check, ChevronDown, Copy, Download, Moon, RotateCcw, Sun } from 'lucide-react'
|
import { Check, ChevronDown, Copy, Download, RotateCcw } from 'lucide-react'
|
||||||
|
|
||||||
const directions = ['0° →', '45° ↗', '90° ↑', '135° ↖', '180° ←', '225° ↙', '270° ↓', '315° ↘']
|
const directions = ['0° →', '45° ↗', '90° ↑', '135° ↖', '180° ←', '225° ↙', '270° ↓', '315° ↘']
|
||||||
|
|
||||||
@@ -11,14 +12,13 @@ export default function GradientPage() {
|
|||||||
const [direction, setDirection] = useState(135)
|
const [direction, setDirection] = useState(135)
|
||||||
const [opacity, setOpacity] = useState(100)
|
const [opacity, setOpacity] = useState(100)
|
||||||
const [type, setType] = useState<'linear' | 'radial'>('linear')
|
const [type, setType] = useState<'linear' | 'radial'>('linear')
|
||||||
const [dark, setDark] = useState(true)
|
|
||||||
const [copied, setCopied] = useState(false)
|
const [copied, setCopied] = useState(false)
|
||||||
const gradient = useMemo(() => type === 'linear' ? `linear-gradient(${direction}deg, ${start} 0%, ${end} 100%)` : `radial-gradient(circle, ${start} 0%, ${end} 100%)`, [direction, end, start, type])
|
const gradient = useMemo(() => type === 'linear' ? `linear-gradient(${direction}deg, ${start} 0%, ${end} 100%)` : `radial-gradient(circle, ${start} 0%, ${end} 100%)`, [direction, end, start, type])
|
||||||
const css = `background: ${gradient};\nopacity: ${opacity / 100};`
|
const css = `background: ${gradient};\nopacity: ${opacity / 100};`
|
||||||
const reset = () => { setStart('#1769D2'); setEnd('#00A8C7'); setDirection(135); setOpacity(100); setType('linear') }
|
const reset = () => { setStart('#1769D2'); setEnd('#00A8C7'); setDirection(135); setOpacity(100); setType('linear') }
|
||||||
const copyCss = async () => { await navigator.clipboard?.writeText(css); setCopied(true); setTimeout(() => setCopied(false), 1400) }
|
const copyCss = async () => { await navigator.clipboard?.writeText(css); setCopied(true); setTimeout(() => setCopied(false), 1400) }
|
||||||
return <main className={`app-shell ${dark ? 'dark-mode' : ''}`}>
|
return <main className="app-shell">
|
||||||
<header className="topbar"><div className="brand"><span className="brand-mark">EP</span><span>easy-png-tools</span><span className="version">/ GRADIENT</span></div><div className="top-actions"><button className="icon-btn" aria-label="Toggle theme" onClick={() => setDark(!dark)}>{dark ? <Sun size={17} /> : <Moon size={17} />}</button></div></header>
|
<TopBar section="GRADIENT" status="LIVE PREVIEW" />
|
||||||
<div className="tool-page"><div className="eyebrow">PNG PROCESSING <span>/</span> SINGLE TOOL</div><div className="tool-title"><div><h1>Gradient background.</h1><p className="lede">Create a clean, export-ready gradient with precise control over color, direction and transparency.</p></div><span className="tool-status"><i /> LIVE PREVIEW</span></div>
|
<div className="tool-page"><div className="eyebrow">PNG PROCESSING <span>/</span> SINGLE TOOL</div><div className="tool-title"><div><h1>Gradient background.</h1><p className="lede">Create a clean, export-ready gradient with precise control over color, direction and transparency.</p></div><span className="tool-status"><i /> LIVE PREVIEW</span></div>
|
||||||
<div className="gradient-layout"><section className="settings-panel"><div className="panel-heading"><div><span className="label">GRADIENT SETTINGS</span><strong>Configure output</strong></div><span className="step-type">TOOL 01</span></div>
|
<div className="gradient-layout"><section className="settings-panel"><div className="panel-heading"><div><span className="label">GRADIENT SETTINGS</span><strong>Configure output</strong></div><span className="step-type">TOOL 01</span></div>
|
||||||
<div className="setting-group"><label>GRADIENT TYPE</label><div className="segmented wide"><button className={type === 'linear' ? 'selected' : ''} onClick={() => setType('linear')}>Linear</button><button className={type === 'radial' ? 'selected' : ''} onClick={() => setType('radial')}>Radial</button></div></div>
|
<div className="setting-group"><label>GRADIENT TYPE</label><div className="segmented wide"><button className={type === 'linear' ? 'selected' : ''} onClick={() => setType('linear')}>Linear</button><button className={type === 'radial' ? 'selected' : ''} onClick={() => setType('radial')}>Radial</button></div></div>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import TopBar from '@/components/top-bar'
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { useMemo, useState } from "react"
|
import { useMemo, useState } from "react"
|
||||||
import { ArrowUpRight, FileImage, Filter, Search, Sparkles } from "lucide-react"
|
import { ArrowUpRight, FileImage, Filter, Search, Sparkles } from "lucide-react"
|
||||||
@@ -17,11 +18,11 @@ export default function ListToolsPage() {
|
|||||||
const [query, setQuery] = useState("")
|
const [query, setQuery] = useState("")
|
||||||
const [active, setActive] = useState("ALL")
|
const [active, setActive] = useState("ALL")
|
||||||
const filtered = useMemo(() => groups.map(group => ({ ...group, tools: group.tools.filter(([name, description]) => (active === "ALL" || active === group.name) && `${name} ${description}`.toLowerCase().includes(query.toLowerCase())) })).filter(group => group.tools.length), [query, active])
|
const filtered = useMemo(() => groups.map(group => ({ ...group, tools: group.tools.filter(([name, description]) => (active === "ALL" || active === group.name) && `${name} ${description}`.toLowerCase().includes(query.toLowerCase())) })).filter(group => group.tools.length), [query, active])
|
||||||
return <main className="catalog-page"><header className="catalog-nav"><Link href="/" className="catalog-brand">easy-png-tools</Link><nav><Link href="/">Workspace</Link><Link className="current" href="/easy-png-tools/list-tools">Catalog</Link></nav><span className="catalog-nav-status">LOCAL MODE / READY</span></header>
|
return <main className="app-shell"><TopBar section="CATALOG" status="LOCAL MODE / READY" /><div className="catalog-page">
|
||||||
<div className="catalog-head"><div><div className="eyebrow">EASY-PNG-TOOLS / CATALOG</div><h1>Tool catalog</h1><p>Focused utilities for working with PNG. Inspect, transform, and export — locally in your browser.</p></div><div className="catalog-total"><b>32</b><span>TOOLS<br />AVAILABLE</span></div></div>
|
<div className="catalog-head"><div><div className="eyebrow">EASY-PNG-TOOLS / CATALOG</div><h1>Tool catalog</h1><p>Focused utilities for working with PNG. Inspect, transform, and export — locally in your browser.</p></div><div className="catalog-total"><b>32</b><span>TOOLS<br />AVAILABLE</span></div></div>
|
||||||
<div className="catalog-toolbar"><label className="catalog-search"><Search size={16} /><input aria-label="Search tools" placeholder="Search tools..." value={query} onChange={e => setQuery(e.target.value)} /></label><div className="catalog-filters"><Filter size={15} />{["ALL", ...groups.map(g => g.name)].map(name => <button key={name} className={active === name ? "active" : ""} onClick={() => setActive(name)}>{name}</button>)}</div></div>
|
<div className="catalog-toolbar"><label className="catalog-search"><Search size={16} /><input aria-label="Search tools" placeholder="Search tools..." value={query} onChange={e => setQuery(e.target.value)} /></label><div className="catalog-filters"><Filter size={15} />{["ALL", ...groups.map(g => g.name)].map(name => <button key={name} className={active === name ? "active" : ""} onClick={() => setActive(name)}>{name}</button>)}</div></div>
|
||||||
<div className="catalog-groups">{filtered.map(group => <section className="catalog-group" key={group.name}><div className="group-title"><span>{group.name}</span><i>{String(group.tools.length).padStart(2, "0")} TOOLS</i></div><div className="tool-cards">{group.tools.map(([name, description, href], index) => <Link className="tool-card" href={href || "#"} key={name} onClick={e => { if (!href) e.preventDefault() }}><span className="tool-icon"><FileImage size={19} /></span><span className="tool-copy"><strong>{name}</strong><span>{description}</span></span><span className="tool-index">{String(index + 1).padStart(2, "0")}</span><ArrowUpRight size={16} className="tool-arrow" /></Link>)}</div></section>)}</div>
|
<div className="catalog-groups">{filtered.map(group => <section className="catalog-group" key={group.name}><div className="group-title"><span>{group.name}</span><i>{String(group.tools.length).padStart(2, "0")} TOOLS</i></div><div className="tool-cards">{group.tools.map(([name, description, href], index) => <Link className="tool-card" href={href || "#"} key={name} onClick={e => { if (!href) e.preventDefault() }}><span className="tool-icon"><FileImage size={19} /></span><span className="tool-copy"><strong>{name}</strong><span>{description}</span></span><span className="tool-index">{String(index + 1).padStart(2, "0")}</span><ArrowUpRight size={16} className="tool-arrow" /></Link>)}</div></section>)}</div>
|
||||||
{!filtered.length && <div className="catalog-empty"><Sparkles size={18} /> No tools match your search.</div>}
|
{!filtered.length && <div className="catalog-empty"><Sparkles size={18} /> No tools match your search.</div>}
|
||||||
<footer className="catalog-footer">ALL OPERATIONS RUN LOCALLY <span>•</span> YOUR FILES NEVER LEAVE THIS DEVICE</footer>
|
<footer className="catalog-footer">ALL OPERATIONS RUN LOCALLY <span>•</span> YOUR FILES NEVER LEAVE THIS DEVICE</footer>
|
||||||
</main>
|
</div></main>
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+4
-4
@@ -1,7 +1,8 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import TopBar from '@/components/top-bar'
|
||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { ArrowDownToLine, Check, ChevronDown, CircleHelp, Download, GripVertical, Link2, Moon, MoreHorizontal, Plus, RotateCcw, Settings2, SlidersHorizontal, Sun, Upload, X } from 'lucide-react'
|
import { ArrowDownToLine, Check, ChevronDown, Download, GripVertical, Link2, MoreHorizontal, Plus, RotateCcw, Settings2, SlidersHorizontal, Upload, X } from 'lucide-react'
|
||||||
|
|
||||||
const initialSteps = [
|
const initialSteps = [
|
||||||
{ id: 1, title: 'Gradient background', type: 'BACKGROUND' },
|
{ id: 1, title: 'Gradient background', type: 'BACKGROUND' },
|
||||||
@@ -20,14 +21,13 @@ export default function Page() {
|
|||||||
const [radius, setRadius] = useState(18)
|
const [radius, setRadius] = useState(18)
|
||||||
const [outline, setOutline] = useState(2)
|
const [outline, setOutline] = useState(2)
|
||||||
const [language, setLanguage] = useState('RU')
|
const [language, setLanguage] = useState('RU')
|
||||||
const [dark, setDark] = useState(false)
|
|
||||||
const [showIntermediate, setShowIntermediate] = useState(true)
|
const [showIntermediate, setShowIntermediate] = useState(true)
|
||||||
const [gradient, setGradient] = useState('#DCEBFF')
|
const [gradient, setGradient] = useState('#DCEBFF')
|
||||||
const gradientStyle = useMemo(() => ({ background: `linear-gradient(${angle}deg, ${gradient}, #8BC8F5)` }), [angle, gradient])
|
const gradientStyle = useMemo(() => ({ background: `linear-gradient(${angle}deg, ${gradient}, #8BC8F5)` }), [angle, gradient])
|
||||||
const finalStyle = { ...gradientStyle, borderRadius: radius, boxShadow: `0 0 0 ${outline}px #16202B` }
|
const finalStyle = { ...gradientStyle, borderRadius: radius, boxShadow: `0 0 0 ${outline}px #16202B` }
|
||||||
|
|
||||||
return <main className={dark ? 'app-shell dark-mode' : 'app-shell'}>
|
return <main className="app-shell">
|
||||||
<header className="topbar"><div className="brand"><span className="brand-mark">EP</span><span>easy-png-tools</span><span className="version">/ DEMO</span></div><div className="top-actions"><span className="status"><i /> AUTO PIPELINE</span><button className="icon-btn" aria-label="Help"><CircleHelp size={17} /></button><button className="icon-btn" aria-label="Toggle theme" onClick={() => setDark(!dark)}>{dark ? <Sun size={17} /> : <Moon size={17} />}</button><div className="language"><button className={language === 'RU' ? 'active' : ''} onClick={() => setLanguage('RU')}>RU</button><button className={language === 'EN' ? 'active' : ''} onClick={() => setLanguage('EN')}>EN</button></div></div></header>
|
<TopBar section="WORKSPACE" status="AUTO PIPELINE" />
|
||||||
<div className="page-grid">
|
<div className="page-grid">
|
||||||
<section className="workspace"><div className="eyebrow">PNG PROCESSING <span>/</span> WORKSPACE</div><div className="title-row"><div><h1>Build your image pipeline.</h1><p className="lede">Chain simple tools together. Every change is processed automatically and previewed at each stage.</p></div><div className="file-chip"><Upload size={15} /><span>source.png</span><b>1.8 MB</b></div></div>
|
<section className="workspace"><div className="eyebrow">PNG PROCESSING <span>/</span> WORKSPACE</div><div className="title-row"><div><h1>Build your image pipeline.</h1><p className="lede">Chain simple tools together. Every change is processed automatically and previewed at each stage.</p></div><div className="file-chip"><Upload size={15} /><span>source.png</span><b>1.8 MB</b></div></div>
|
||||||
<div className="pipeline-head"><div><span className="label">PROCESSING PIPELINE</span><strong>{steps.length} active steps <em>• LIVE</em></strong></div><button className="add-btn" onClick={() => setSteps([...steps, { id: Date.now(), title: 'New adjustment', type: 'STYLE' }])}><Plus size={15} /> Add tool</button></div>
|
<div className="pipeline-head"><div><span className="label">PROCESSING PIPELINE</span><strong>{steps.length} active steps <em>• LIVE</em></strong></div><button className="add-btn" onClick={() => setSteps([...steps, { id: Date.now(), title: 'New adjustment', type: 'STYLE' }])}><Plus size={15} /> Add tool</button></div>
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import Link from "next/link"
|
||||||
|
import { CircleHelp, Moon, Sun } from "lucide-react"
|
||||||
|
import { usePathname } from "next/navigation"
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
|
|
||||||
|
const links = [
|
||||||
|
["Workspace", "/"],
|
||||||
|
["Catalog", "/easy-png-tools/list-tools"],
|
||||||
|
["Gradient", "/easy-png-tools/gradient"],
|
||||||
|
["Background remover", "/easy-png-tools/background-remover"],
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export function TopBar({ section = "WORKSPACE", status = "LOCAL MODE / READY" }: { section?: string; status?: string }) {
|
||||||
|
const pathname = usePathname()
|
||||||
|
const [dark, setDark] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const stored = window.localStorage.getItem("ep-theme")
|
||||||
|
const isDark = stored === "dark"
|
||||||
|
setDark(isDark)
|
||||||
|
document.documentElement.classList.toggle("dark-mode", isDark)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const toggleTheme = () => {
|
||||||
|
const next = !dark
|
||||||
|
setDark(next)
|
||||||
|
document.documentElement.classList.toggle("dark-mode", next)
|
||||||
|
window.localStorage.setItem("ep-theme", next ? "dark" : "light")
|
||||||
|
}
|
||||||
|
|
||||||
|
return <header className="topbar"><Link href="/" className="brand"><span className="brand-mark">EP</span><span>easy-png-tools</span><span className="version">/ {section}</span></Link><nav className="top-nav" aria-label="Primary navigation">{links.map(([label, href]) => <Link key={href} className={pathname === href ? "active" : ""} href={href}>{label}</Link>)}</nav><div className="top-actions"><span className="status"><i /> {status}</span><button className="icon-btn" aria-label="Help"><CircleHelp size={17} /></button><button className="icon-btn" aria-label="Toggle theme" onClick={toggleTheme}>{dark ? <Sun size={17} /> : <Moon size={17} />}</button><div className="language"><button className="active">RU</button><span>/</span><button>EN</button></div></div></header>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TopBar
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"html": "node extract-static.mjs .next\\server\\app ..\\refs-html",
|
|
||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
Generated
+1
-4
@@ -4,9 +4,6 @@ settings:
|
|||||||
autoInstallPeers: true
|
autoInstallPeers: true
|
||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
overrides:
|
|
||||||
hono: 4.12.25
|
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
@@ -268,7 +265,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==}
|
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==}
|
||||||
engines: {node: '>=18.14.1'}
|
engines: {node: '>=18.14.1'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
hono: 4.12.25
|
hono: ^4
|
||||||
|
|
||||||
'@img/colour@1.1.0':
|
'@img/colour@1.1.0':
|
||||||
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
|
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Reference in New Issue
Block a user