mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
refactor: move old libs and components to old folder
This commit is contained in:
@@ -1,83 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
interface Props {
|
||||
variant?: "primary" | "secondary";
|
||||
type?: "button" | "submit";
|
||||
disabled?: boolean;
|
||||
busy?: boolean;
|
||||
busyText?: string;
|
||||
fullWidth?: boolean;
|
||||
onclick?: () => void;
|
||||
children: Snippet;
|
||||
}
|
||||
|
||||
let {
|
||||
variant = "primary",
|
||||
type = "button",
|
||||
disabled = false,
|
||||
busy = false,
|
||||
busyText = "",
|
||||
fullWidth = false,
|
||||
onclick,
|
||||
children,
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<button
|
||||
{type}
|
||||
class={fullWidth ? `${variant} fullwidth` : variant}
|
||||
aria-busy={busy}
|
||||
disabled={disabled || busy}
|
||||
{onclick}
|
||||
>
|
||||
{#if busy && busyText}
|
||||
{busyText}
|
||||
{:else}
|
||||
{@render children()}
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<style>
|
||||
button {
|
||||
padding: var(--space-2) var(--space-3);
|
||||
border-radius: var(--radius-s);
|
||||
border: 1px solid transparent;
|
||||
font-weight: 600;
|
||||
font-size: var(--text-m);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background var(--transition-fast),
|
||||
border-color var(--transition-fast),
|
||||
color var(--transition-fast);
|
||||
}
|
||||
|
||||
button.primary {
|
||||
background: var(--accent);
|
||||
color: var(--accent-contrast);
|
||||
}
|
||||
|
||||
button.primary:hover:not(:disabled) {
|
||||
background: var(--accent-hover);
|
||||
}
|
||||
|
||||
button.secondary {
|
||||
background: var(--surface);
|
||||
color: var(--text);
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
button.secondary:hover:not(:disabled) {
|
||||
border-color: var(--link);
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.55;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,56 +0,0 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
id: string;
|
||||
label: string;
|
||||
checked?: boolean;
|
||||
hint?: string;
|
||||
}
|
||||
|
||||
let { id, label, checked = $bindable(false), hint }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="checkbox-row">
|
||||
<label class="checkbox" for={id}>
|
||||
<input {id} type="checkbox" bind:checked />
|
||||
{label}
|
||||
</label>
|
||||
{#if hint}
|
||||
<p class="hint text-caption text-muted">{hint}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-3);
|
||||
padding: calc(var(--space-1) + 2px) 0;
|
||||
border-bottom: 1px dashed var(--border);
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
cursor: pointer;
|
||||
font-size: var(--text-caption, var(--text-s));
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
cursor: pointer;
|
||||
accent-color: var(--accent);
|
||||
}
|
||||
|
||||
label:hover {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.hint {
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
@@ -1,87 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Field from "./Field.svelte";
|
||||
import { t } from "$lib/i18n/t";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
label: string;
|
||||
value?: string;
|
||||
hint?: string;
|
||||
pipetteActive?: boolean;
|
||||
onPipetteToggle?: () => void;
|
||||
}
|
||||
|
||||
let {
|
||||
id,
|
||||
label,
|
||||
value = $bindable("#000000"),
|
||||
hint,
|
||||
pipetteActive = false,
|
||||
onPipetteToggle,
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<Field {id} {label} {hint}>
|
||||
<div class="row">
|
||||
<input {id} class="control swatch" type="color" bind:value />
|
||||
{#if onPipetteToggle}
|
||||
<button
|
||||
type="button"
|
||||
class="pipette"
|
||||
aria-label={t("ui.pipette")}
|
||||
aria-pressed={pipetteActive}
|
||||
title={t("ui.pipette")}
|
||||
onclick={onPipetteToggle}
|
||||
>
|
||||
◎
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</Field>
|
||||
|
||||
<style>
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.swatch {
|
||||
height: var(--control-height);
|
||||
width: 3.5rem;
|
||||
padding: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pipette {
|
||||
flex: none;
|
||||
width: var(--control-height);
|
||||
height: var(--control-height);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-s);
|
||||
background: var(--surface);
|
||||
color: var(--text-muted);
|
||||
font-size: 1.1rem;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
border-color var(--transition-fast),
|
||||
color var(--transition-fast),
|
||||
background var(--transition-fast);
|
||||
}
|
||||
|
||||
.pipette:hover {
|
||||
border-color: var(--link);
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
.pipette[aria-pressed="true"] {
|
||||
border-color: var(--link);
|
||||
color: var(--link);
|
||||
background: color-mix(in srgb, var(--accent) 10%, var(--surface));
|
||||
}
|
||||
</style>
|
||||
@@ -1,38 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
hint?: string;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let { title, hint, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="empty panel">
|
||||
<p class="title">{title}</p>
|
||||
{#if hint}
|
||||
<p class="text-caption text-muted">{hint}</p>
|
||||
{/if}
|
||||
{#if children}
|
||||
{@render children()}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--space-1);
|
||||
min-height: 8rem;
|
||||
padding: var(--space-4);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
@@ -1,54 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
label: string;
|
||||
hint?: string;
|
||||
children: Snippet;
|
||||
}
|
||||
|
||||
let { id, label, hint, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="field">
|
||||
<label class="text-caption text-muted" for={id}>{label}</label>
|
||||
<div class="control-slot">
|
||||
{@render children()}
|
||||
{#if hint}
|
||||
<p class="hint text-caption text-muted">{hint}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-3);
|
||||
padding: calc(var(--space-1) + 2px) 0;
|
||||
border-bottom: 1px dashed var(--border);
|
||||
}
|
||||
|
||||
label {
|
||||
flex: none;
|
||||
max-width: 45%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.control-slot {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.hint {
|
||||
margin: 0;
|
||||
align-self: flex-end;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
@@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Field from "./Field.svelte";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
label: string;
|
||||
value?: string;
|
||||
options: { value: string; label: string }[];
|
||||
hint?: string;
|
||||
}
|
||||
|
||||
let { id, label, value = $bindable(""), options, hint }: Props = $props();
|
||||
</script>
|
||||
|
||||
<Field {id} {label} {hint}>
|
||||
<select {id} class="control" bind:value>
|
||||
{#each options as option (option.value)}
|
||||
<option value={option.value}>{option.label}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</Field>
|
||||
@@ -1,127 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Field from "./Field.svelte";
|
||||
import { t } from "$lib/i18n/t";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
label: string;
|
||||
value?: number;
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
default?: number;
|
||||
hint?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
id,
|
||||
label,
|
||||
value = $bindable(0),
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
default: defaultValue,
|
||||
hint,
|
||||
}: Props = $props();
|
||||
|
||||
function decrement() {
|
||||
if (min !== undefined && value <= min) return;
|
||||
value = Math.max(min ?? -Infinity, value - (step ?? 1));
|
||||
}
|
||||
|
||||
function increment() {
|
||||
if (max !== undefined && value >= max) return;
|
||||
value = Math.min(max ?? Infinity, value + (step ?? 1));
|
||||
}
|
||||
|
||||
function reset() {
|
||||
if (defaultValue !== undefined) value = defaultValue;
|
||||
}
|
||||
|
||||
const resetDisabled = $derived(
|
||||
defaultValue === undefined || value === defaultValue,
|
||||
);
|
||||
</script>
|
||||
|
||||
<Field {id} {label} {hint}>
|
||||
<div class="row">
|
||||
<button
|
||||
type="button"
|
||||
class="step"
|
||||
aria-label={t("ui.decrease")}
|
||||
onclick={decrement}>−</button
|
||||
>
|
||||
<input {id} type="range" {min} {max} {step} bind:value />
|
||||
<button
|
||||
type="button"
|
||||
class="step"
|
||||
aria-label={t("ui.increase")}
|
||||
onclick={increment}>+</button
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="step"
|
||||
aria-label={t("ui.reset")}
|
||||
disabled={resetDisabled}
|
||||
onclick={reset}
|
||||
>
|
||||
↺
|
||||
</button>
|
||||
<output>{value}</output>
|
||||
</div>
|
||||
</Field>
|
||||
|
||||
<style>
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
width: 100%;
|
||||
max-width: 22rem;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
flex: 1;
|
||||
min-width: 3rem;
|
||||
accent-color: var(--link);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.step {
|
||||
flex: none;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-s);
|
||||
background: var(--surface);
|
||||
color: var(--text);
|
||||
font-size: 0.85rem;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
border-color var(--transition-fast),
|
||||
color var(--transition-fast);
|
||||
}
|
||||
|
||||
.step:hover:not(:disabled) {
|
||||
border-color: var(--link);
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
.step:disabled {
|
||||
opacity: 0.45;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
output {
|
||||
flex: none;
|
||||
min-width: 3ch;
|
||||
text-align: right;
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--text-s);
|
||||
}
|
||||
</style>
|
||||
@@ -1,47 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Field from "./Field.svelte";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
label: string;
|
||||
value?: string | number;
|
||||
type?: "number" | "text";
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
hint?: string;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
id,
|
||||
label,
|
||||
value = $bindable(""),
|
||||
type = "text",
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
hint,
|
||||
placeholder,
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<Field {id} {label} {hint}>
|
||||
<input
|
||||
class="control"
|
||||
{id}
|
||||
{type}
|
||||
{min}
|
||||
{max}
|
||||
{step}
|
||||
{placeholder}
|
||||
bind:value
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<style>
|
||||
input.control::placeholder {
|
||||
color: var(--text-muted);
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user