feat: fix demo page to correspond refs
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
<script lang="ts">
|
||||
import BlueprintGrid from "./BlueprintGrid.svelte";
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<div class="app-shell">
|
||||
<BlueprintGrid />
|
||||
<div class="app-content">
|
||||
{@render children()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.app-shell {
|
||||
position: relative;
|
||||
min-height: 100dvh;
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
|
||||
.app-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
@@ -1,16 +1,19 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
import { Check } from "@lucide/svelte";
|
||||
|
||||
type Tone = "default" | "accent" | "success" | "amber";
|
||||
|
||||
interface Props {
|
||||
tone?: Tone;
|
||||
check?: boolean;
|
||||
children: Snippet;
|
||||
}
|
||||
let { tone = "default", children }: Props = $props();
|
||||
let { tone = "default", check = false, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<span class="badge badge--{tone}">
|
||||
{#if check}<Check size={12} />{/if}
|
||||
{#if children}{@render children()}{/if}
|
||||
</span>
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<div class="blueprint-grid" aria-hidden="true"></div>
|
||||
|
||||
<style>
|
||||
.blueprint-grid {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background-image:
|
||||
linear-gradient(
|
||||
to right,
|
||||
color-mix(in srgb, var(--line) 45%, transparent) 1px,
|
||||
transparent 1px
|
||||
),
|
||||
linear-gradient(
|
||||
to bottom,
|
||||
color-mix(in srgb, var(--line) 45%, transparent) 1px,
|
||||
transparent 1px
|
||||
);
|
||||
background-size: 32px 32px;
|
||||
opacity: 0.55;
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,14 @@
|
||||
<script lang="ts">
|
||||
import Field from "./Field.svelte";
|
||||
import { ChevronDown } from "@lucide/svelte";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
value: string;
|
||||
dark?: boolean;
|
||||
chevron?: boolean;
|
||||
oninput?: (value: string) => void;
|
||||
}
|
||||
let { label, value = $bindable(), oninput }: Props = $props();
|
||||
let { label, value = $bindable(), dark = false, chevron = false, oninput }: Props = $props();
|
||||
|
||||
function handle(e: Event) {
|
||||
value = (e.target as HTMLInputElement).value;
|
||||
@@ -14,43 +16,53 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Field {label}>
|
||||
<div class="control-block">
|
||||
<label>{label}</label>
|
||||
<div class="color-field">
|
||||
<input type="color" class="color-swatch" {value} oninput={handle} />
|
||||
<input
|
||||
type="text"
|
||||
class="color-hex"
|
||||
{value}
|
||||
oninput={handle}
|
||||
spellcheck="false"
|
||||
/>
|
||||
<span class="swatch" class:dark style="background:{value}"></span>
|
||||
<input type="text" aria-label={label} {value} oninput={handle} spellcheck="false" />
|
||||
{#if chevron}<ChevronDown size={14} />{/if}
|
||||
</div>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.control-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
label {
|
||||
font: 10px var(--font-mono);
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
}
|
||||
.color-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
.color-swatch {
|
||||
width: 2rem;
|
||||
.swatch {
|
||||
width: 1.6rem;
|
||||
height: 1.6rem;
|
||||
padding: 0;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
flex: none;
|
||||
}
|
||||
.color-hex {
|
||||
.color-field input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
padding: 0.3rem 0.5rem;
|
||||
padding: 0.35rem 0.5rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.color-field :global(svg) {
|
||||
color: var(--muted);
|
||||
flex: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,23 +1,34 @@
|
||||
<script lang="ts">
|
||||
import { Download } from "@lucide/svelte";
|
||||
import Button from "./Button.svelte";
|
||||
import { Download, ArrowDownToLine } from "@lucide/svelte";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
size?: string;
|
||||
onclick?: () => void;
|
||||
}
|
||||
let { label, size, onclick }: Props = $props();
|
||||
let { label, onclick }: Props = $props();
|
||||
</script>
|
||||
|
||||
<Button icon={Download} variant="primary" onclick={() => onclick?.()}>
|
||||
{label}{#if size}<span class="dl-size">{size}</span>{/if}
|
||||
</Button>
|
||||
<button class="download-btn" type="button" onclick={() => onclick?.()}>
|
||||
<Download size={16} />
|
||||
{label}
|
||||
<ArrowDownToLine size={14} />
|
||||
</button>
|
||||
|
||||
<style>
|
||||
.dl-size {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10px;
|
||||
opacity: 0.8;
|
||||
.download-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border: 1px solid var(--blue);
|
||||
background: var(--blue);
|
||||
color: #fff;
|
||||
font: 12px var(--font-mono);
|
||||
letter-spacing: 0.04em;
|
||||
padding: 9px 14px;
|
||||
border-radius: var(--radius);
|
||||
cursor: pointer;
|
||||
}
|
||||
.download-btn:hover {
|
||||
background: color-mix(in srgb, var(--blue) 88%, #000);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,22 +9,23 @@
|
||||
let { compact = false, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="field-grid" class:compact>
|
||||
<div class="controls" class:compact>
|
||||
{@render children()}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.field-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1.1fr 1fr 1.2fr;
|
||||
gap: 16px;
|
||||
.controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
.field-grid.compact {
|
||||
.controls.compact {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 14px;
|
||||
}
|
||||
@media (max-width: 800px) {
|
||||
.field-grid,
|
||||
.field-grid.compact {
|
||||
.controls.compact {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<div class="meta-row">
|
||||
<span class="meta-caption">{caption}</span>
|
||||
<span class="meta-value">{value}</span>
|
||||
<b class="meta-value">{value}</b>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -3,14 +3,19 @@
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
caption: string;
|
||||
children: Snippet;
|
||||
}
|
||||
let { label, children }: Props = $props();
|
||||
|
||||
let { label, caption, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="preview-tile">
|
||||
<span class="tile-label">{label}</span>
|
||||
<div class="tile-canvas">{@render children()}</div>
|
||||
<div class="tile-label">
|
||||
<span>{label}</span>
|
||||
<b>{caption}</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -23,15 +28,25 @@
|
||||
padding: 0.4rem;
|
||||
background: var(--panel);
|
||||
}
|
||||
.tile-label {
|
||||
font: 10px var(--font-mono);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--blue);
|
||||
}
|
||||
.tile-canvas {
|
||||
border-radius: var(--radius);
|
||||
overflow: hidden;
|
||||
min-height: 120px;
|
||||
}
|
||||
.tile-label {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.tile-label span {
|
||||
font: 10px var(--font-mono);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--blue);
|
||||
}
|
||||
.tile-label b {
|
||||
font: 400 10px var(--font-mono);
|
||||
color: var(--muted);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
title: string;
|
||||
meta?: string;
|
||||
actions?: Snippet;
|
||||
unwrapActions?: boolean;
|
||||
}
|
||||
|
||||
let { label, title, meta, actions }: Props = $props();
|
||||
let { label, title, meta, actions, unwrapActions = false }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="section-label">
|
||||
@@ -18,9 +19,13 @@
|
||||
<strong>{title}{#if meta}<em>{meta}</em>{/if}</strong>
|
||||
</div>
|
||||
{#if actions}
|
||||
<div class="section-actions">
|
||||
{#if unwrapActions}
|
||||
{@render actions()}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="section-actions">
|
||||
{@render actions()}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<button
|
||||
type="button"
|
||||
class="segment"
|
||||
class:active={value === opt.value}
|
||||
class:selected={value === opt.value}
|
||||
aria-pressed={value === opt.value}
|
||||
onclick={() => select(opt.value)}
|
||||
>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script lang="ts">
|
||||
import Field from "./Field.svelte";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
value: number;
|
||||
@@ -26,34 +24,33 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Field {label}>
|
||||
<div class="slider-field">
|
||||
<input type="range" {min} {max} {step} {value} oninput={handle} />
|
||||
<span class="slider-value">
|
||||
{value}
|
||||
{#if suffix}
|
||||
{suffix}
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
</Field>
|
||||
<div class="control-block">
|
||||
<label>{label} <output>{value}{suffix}</output></label>
|
||||
<input type="range" {min} {max} {step} {value} oninput={handle} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.slider-field {
|
||||
.control-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
gap: 0.5rem;
|
||||
font: 10px var(--font-mono);
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
}
|
||||
output {
|
||||
font: 11px var(--font-mono);
|
||||
color: var(--foreground);
|
||||
}
|
||||
input[type="range"] {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
accent-color: var(--blue);
|
||||
}
|
||||
.slider-value {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
color: var(--foreground);
|
||||
min-width: 4ch;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<span class="status-dot" aria-hidden="true"></span>
|
||||
<i class="status-dot" aria-hidden="true"></i>
|
||||
|
||||
<style>
|
||||
.status-dot {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
import { GripVertical, X } from "@lucide/svelte";
|
||||
import { GripVertical, X, Ellipsis } from "@lucide/svelte";
|
||||
|
||||
interface Props {
|
||||
index: number;
|
||||
@@ -15,10 +15,8 @@
|
||||
</script>
|
||||
|
||||
<article class="step-card">
|
||||
<div class="step-rail">
|
||||
<span class="step-index">{index.toString().padStart(2, "0")}</span>
|
||||
<span class="drag" aria-hidden="true"><GripVertical size={16} /></span>
|
||||
</div>
|
||||
<div class="step-index">{index.toString().padStart(2, "0")}</div>
|
||||
<GripVertical size={16} class="drag" aria-hidden="true" />
|
||||
<div class="step-body">
|
||||
<div class="step-heading">
|
||||
<div class="step-heading-text">
|
||||
@@ -35,43 +33,46 @@
|
||||
>
|
||||
<X size={16} />
|
||||
</button>
|
||||
<Ellipsis size={17} />
|
||||
</div>
|
||||
</div>
|
||||
{#if children}
|
||||
<div class="step-content">{@render children()}</div>
|
||||
{@render children()}
|
||||
{/if}
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<style>
|
||||
.step-card {
|
||||
display: flex;
|
||||
display: grid;
|
||||
grid-template-columns: 46px 1fr;
|
||||
grid-template-rows: auto 1fr;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
background: var(--panel);
|
||||
overflow: hidden;
|
||||
}
|
||||
.step-rail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
min-width: 46px;
|
||||
padding: 17px 0 17px 15px;
|
||||
border-right: 1px solid var(--line);
|
||||
}
|
||||
.step-index {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
font: 600 22px var(--font-mono);
|
||||
line-height: 1;
|
||||
color: var(--blue);
|
||||
padding: 17px 0 6px 15px;
|
||||
border-right: 1px solid var(--line);
|
||||
}
|
||||
.drag {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
color: var(--muted);
|
||||
cursor: grab;
|
||||
display: inline-flex;
|
||||
padding: 0 0 17px 15px;
|
||||
border-right: 1px solid var(--line);
|
||||
}
|
||||
.step-body {
|
||||
flex: 1;
|
||||
grid-column: 2;
|
||||
grid-row: 1 / span 2;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -115,10 +116,7 @@
|
||||
.step-remove:hover {
|
||||
color: var(--danger);
|
||||
}
|
||||
.step-content {
|
||||
.step-body > :not(.step-heading) {
|
||||
padding: 0.75rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
aria-label={label}
|
||||
onclick={handle}
|
||||
>
|
||||
<span class="toggle-knob"></span>
|
||||
<i class="toggle-knob"></i>
|
||||
</button>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
let { label, checked = $bindable(), onchange }: Props = $props();
|
||||
</script>
|
||||
|
||||
<label class="toggle-row">
|
||||
<div class="toggle-row">
|
||||
<span>{label}</span>
|
||||
<Toggle bind:checked {onchange} {label} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.toggle-row {
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
</script>
|
||||
|
||||
<header class="topbar">
|
||||
<div class="brand">
|
||||
<a class="brand" href={resolve("/")}>
|
||||
<span class="brand-mark">EP</span>
|
||||
<span>easy-png-tools</span>
|
||||
{#if crumb}<span class="version">{crumb}</span>{/if}
|
||||
</div>
|
||||
</a>
|
||||
<nav class="nav">
|
||||
<a href={resolve("/preview/demo")}>Workspace</a>
|
||||
<a href={resolve("/preview/list-tools")}>Catalog</a>
|
||||
@@ -47,7 +47,7 @@
|
||||
class="lang-btn"
|
||||
class:active={lang === "RU"}
|
||||
onclick={() => (lang = "RU")}>RU</button
|
||||
>
|
||||
><span class="lang-div">/</span>
|
||||
<button
|
||||
type="button"
|
||||
class="lang-btn"
|
||||
@@ -138,6 +138,11 @@
|
||||
.lang-btn + .lang-btn {
|
||||
border-left: 1px solid var(--line);
|
||||
}
|
||||
.lang-div {
|
||||
color: var(--muted);
|
||||
font: 10px var(--font-mono);
|
||||
align-self: center;
|
||||
}
|
||||
.lang-btn.active {
|
||||
background: var(--foreground);
|
||||
color: var(--background);
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
class="ws"
|
||||
style="--ws-cols:{columns};--ws-gap:{gap};--ws-pad:{padding};--ws-max:{maxWidth};--ws-sticky:{stickyTop};--ws-pad-mobile:{padMobile};--ws-gap-mobile:{gapMobile};"
|
||||
>
|
||||
<div class="ws-settings">{@render settings()}</div>
|
||||
<div class="ws-preview">{@render preview()}</div>
|
||||
<section class="ws-settings">{@render settings()}</section>
|
||||
{@render preview()}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -47,19 +47,11 @@
|
||||
.ws-settings {
|
||||
min-width: 0;
|
||||
}
|
||||
.ws-preview {
|
||||
position: sticky;
|
||||
top: var(--ws-sticky);
|
||||
min-width: 0;
|
||||
}
|
||||
@media (max-width: 800px) {
|
||||
.ws {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--ws-gap-mobile);
|
||||
padding: var(--ws-pad-mobile);
|
||||
}
|
||||
.ws-preview {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user