refactor: move old libs and components to old folder

This commit is contained in:
2026-09-10 12:01:54 +05:00
parent bf2f8e57c8
commit 3834dadd03
64 changed files with 111 additions and 110 deletions
+950
View File
@@ -0,0 +1,950 @@
import type { ToolEntry } from "../registry";
import { ToolError } from "../../core/errors";
import { solidImage, noiseImage, gradientImage } from "../../core/generate";
import {
colorSpectrum,
drawGrid,
randomColorBlocks,
} from "../../core/gen-tools";
import {
renderTextToImage,
renderEmoji,
type TextFont,
} from "../../core/domText";
import { changeCanvasSize } from "../../core/geometry";
import {
renderWheel,
renderSwatches,
renderBlend,
complementarySet,
triadicSet,
tetradicSet,
analogousSet,
monochromaticSet,
shadeSet,
mixColors,
parseHexList,
stepColors,
sortPalette,
type SortKey,
} from "../../core/palette";
import { num, str, bool } from "../registry-helpers";
function hexToRgba(hex: string, alpha = 255): [number, number, number, number] {
const match = /^#([0-9a-f]{6})$/i.exec(hex.trim());
if (!match) {
throw new ToolError("errors.badHex", { value: hex });
}
const d = match[1];
return [
parseInt(d.slice(0, 2), 16),
parseInt(d.slice(2, 4), 16),
parseInt(d.slice(4, 6), 16),
alpha,
];
}
function paletteParams(baseDefault: string) {
return [
{
id: "baseColor",
label: "Base color",
type: "color" as const,
default: baseDefault,
},
{
id: "width",
label: "Width",
type: "slider" as const,
min: 128,
max: 1024,
step: 16,
default: 512,
},
{
id: "layout",
label: "Layout",
type: "select" as const,
default: "grid",
options: [
{ value: "grid", label: "Grid" },
{ value: "strip", label: "Strip" },
],
},
];
}
export function generateEntries(): ToolEntry[] {
return [
{
id: "create-empty-png",
title: "Create empty PNG",
description:
"Generates a canvas of the chosen size — transparent or filled with color.",
category: "generate",
sourceMode: "none",
params: [
{
id: "width",
label: "Width",
type: "number",
min: 1,
max: 20000,
step: 1,
default: 800,
},
{
id: "height",
label: "Height",
type: "number",
min: 1,
max: 20000,
step: 1,
default: 600,
},
{
id: "transparent",
label: "Transparent",
type: "checkbox",
default: true,
},
{
id: "color",
label: "Color",
type: "color",
default: "#ffffff",
},
],
generate: (p) =>
solidImage(
Math.trunc(num(p, "width")),
Math.trunc(num(p, "height")),
p["transparent"] === true ? [0, 0, 0, 0] : hexToRgba(str(p, "color")),
),
},
{
id: "single-color-png",
title: "Create solid color PNG",
description: "Generates a rectangle of the given size and color.",
category: "generate",
sourceMode: "none",
params: [
{
id: "width",
label: "Width",
type: "number",
min: 1,
max: 20000,
step: 1,
default: 256,
},
{
id: "height",
label: "Height",
type: "number",
min: 1,
max: 20000,
step: 1,
default: 256,
},
{
id: "color",
label: "Color",
type: "color",
default: "#ff0000",
},
],
generate: (p) =>
solidImage(
Math.trunc(num(p, "width")),
Math.trunc(num(p, "height")),
hexToRgba(str(p, "color")),
),
},
{
id: "random-noise-png",
title: "Create random noise PNG",
description:
"Generates an image with random pixels. The seed fixes the result: one seed — one image.",
category: "generate",
sourceMode: "none",
params: [
{
id: "width",
label: "Width",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 512,
},
{
id: "height",
label: "Height",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 512,
},
{
id: "seed",
label: "Seed",
type: "number",
min: 0,
max: 999999999,
step: 1,
default: 1,
},
],
generate: (p) =>
noiseImage(
Math.trunc(num(p, "width")),
Math.trunc(num(p, "height")),
num(p, "seed"),
),
},
{
id: "text-to-png",
title: "Text to PNG",
description:
"Creates a PNG image from text: the canvas is sized to fit the label plus padding.",
category: "generate",
sourceMode: "none",
domOnly: true,
params: [
{
id: "text",
label: "Text",
type: "text",
default: "Hello!",
placeholder: "Your text",
},
{
id: "fontSize",
label: "Font size, px",
type: "slider",
min: 8,
max: 300,
step: 1,
default: 96,
},
{
id: "font",
label: "Font",
type: "select",
default: "sans",
options: [
{ value: "sans", label: "Sans-serif" },
{ value: "serif", label: "Serif" },
{ value: "mono", label: "Monospace" },
],
},
{
id: "bold",
label: "Bold",
type: "checkbox",
default: true,
},
{
id: "color",
label: "Text color",
type: "color",
default: "#111318",
},
{
id: "transparentBg",
label: "Transparent background",
type: "checkbox",
default: false,
},
{
id: "backgroundColor",
label: "Background color",
type: "color",
default: "#ffffff",
},
{
id: "padding",
label: "Padding, px",
type: "slider",
min: 0,
max: 200,
step: 2,
default: 24,
},
],
generate: (p) =>
renderTextToImage({
text: str(p, "text"),
fontSize: num(p, "fontSize"),
font: str(p, "font") as TextFont,
bold: bool(p, "bold"),
color: str(p, "color"),
backgroundColor: str(p, "backgroundColor"),
transparentBg: bool(p, "transparentBg"),
padding: num(p, "padding"),
}),
},
{
id: "emoji-to-png",
title: "Emoji to PNG",
description:
"Renders an emoji or any Unicode symbol as a transparent PNG of the chosen size.",
category: "generate",
sourceMode: "none",
domOnly: true,
params: [
{
id: "emoji",
label: "Emoji / symbol",
type: "text",
default: "\u{1F600}",
},
{
id: "size",
label: "Size",
type: "slider",
min: 32,
max: 1024,
step: 16,
default: 256,
},
],
generate: (p) => renderEmoji(str(p, "emoji"), Math.trunc(num(p, "size"))),
},
{
id: "placeholder-png",
title: "Create Placeholder PNG",
description:
"Generates a placeholder rectangle with its dimensions printed in the center.",
category: "generate",
sourceMode: "none",
domOnly: true,
params: [
{
id: "width",
label: "Width",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 800,
},
{
id: "height",
label: "Height",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 400,
},
{
id: "backgroundColor",
label: "Background",
type: "color",
default: "#dfe2e8",
},
{
id: "color",
label: "Text color",
type: "color",
default: "#5c6470",
},
{
id: "showText",
label: "Print dimensions",
type: "checkbox",
default: true,
},
],
generate: (p) => {
const w = Math.trunc(num(p, "width"));
const h = Math.trunc(num(p, "height"));
const label = renderTextToImage({
text: `${w} × ${h}`,
fontSize: Math.max(12, Math.round(Math.min(w, h) * 0.14)),
font: "sans",
bold: true,
color: str(p, "color"),
backgroundColor: str(p, "backgroundColor"),
transparentBg: false,
padding: 0,
});
return changeCanvasSize(label, w, h, "center");
},
},
{
id: "linear-gradient-png",
title: "Create gradient PNG",
description:
"Generates a smooth transition between two colors, horizontally or vertically.",
category: "generate",
sourceMode: "none",
params: [
{
id: "width",
label: "Width",
type: "number",
min: 1,
max: 20000,
step: 1,
default: 800,
},
{
id: "height",
label: "Height",
type: "number",
min: 1,
max: 20000,
step: 1,
default: 600,
},
{
id: "fromColor",
label: "Start color",
type: "color",
default: "#000000",
},
{
id: "toColor",
label: "End color",
type: "color",
default: "#ffffff",
},
{
id: "direction",
label: "Direction",
type: "select",
default: "horizontal",
options: [
{ value: "horizontal", label: "Horizontal" },
{ value: "vertical", label: "Vertical" },
],
},
],
generate: (p) =>
gradientImage(
Math.trunc(num(p, "width")),
Math.trunc(num(p, "height")),
hexToRgba(str(p, "fromColor")),
hexToRgba(str(p, "toColor")),
str(p, "direction") === "vertical" ? "vertical" : "horizontal",
),
},
{
id: "color-spectrum-png",
title: "Color Spectrum PNG",
description:
"Full hue rainbow 0360° along the chosen axis with adjustable saturation and lightness.",
category: "generate",
sourceMode: "none",
params: [
{
id: "width",
label: "Width",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 1024,
},
{
id: "height",
label: "Height",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 128,
},
{
id: "direction",
label: "Direction",
type: "select",
default: "horizontal",
options: [
{ value: "horizontal", label: "Horizontal" },
{ value: "vertical", label: "Vertical" },
],
},
{
id: "saturation",
label: "Saturation, %",
type: "slider",
min: 0,
max: 100,
step: 1,
default: 100,
},
{
id: "lightness",
label: "Lightness, %",
type: "slider",
min: 0,
max: 100,
step: 1,
default: 50,
},
],
generate: (p) =>
colorSpectrum(
Math.trunc(num(p, "width")),
Math.trunc(num(p, "height")),
str(p, "direction") === "vertical" ? "vertical" : "horizontal",
num(p, "saturation"),
num(p, "lightness"),
),
},
{
id: "random-colors-png",
title: "Random Color Blocks PNG",
description:
"Fills the canvas with random vivid color blocks. Deterministic by seed.",
category: "generate",
sourceMode: "none",
params: [
{
id: "width",
label: "Width",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 512,
},
{
id: "height",
label: "Height",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 512,
},
{
id: "blockSize",
label: "Block size, px",
type: "slider",
min: 4,
max: 256,
step: 2,
default: 64,
},
{
id: "seed",
label: "Seed",
type: "number",
min: 0,
max: 999999999,
step: 1,
default: 7,
},
],
generate: (p) =>
randomColorBlocks(
Math.trunc(num(p, "width")),
Math.trunc(num(p, "height")),
num(p, "blockSize"),
num(p, "seed"),
),
},
{
id: "draw-grid-png",
title: "Draw Grid PNG",
description:
"Draws a grid with custom columns, rows and line width on a transparent or white background.",
category: "generate",
sourceMode: "none",
params: [
{
id: "width",
label: "Width",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 512,
},
{
id: "height",
label: "Height",
type: "number",
min: 1,
max: 5000,
step: 1,
default: 512,
},
{
id: "cols",
label: "Columns",
type: "slider",
min: 1,
max: 64,
step: 1,
default: 8,
},
{
id: "rows",
label: "Rows",
type: "slider",
min: 1,
max: 64,
step: 1,
default: 8,
},
{
id: "lineWidth",
label: "Line width, px",
type: "slider",
min: 1,
max: 40,
step: 1,
default: 2,
},
{
id: "color",
label: "Line color",
type: "color",
default: "#111318",
},
{
id: "transparentBg",
label: "Transparent background",
type: "checkbox",
default: true,
},
],
generate: (p) =>
drawGrid(
Math.trunc(num(p, "width")),
Math.trunc(num(p, "height")),
num(p, "cols"),
num(p, "rows"),
num(p, "lineWidth"),
str(p, "color"),
bool(p, "transparentBg"),
),
},
{
id: "color-wheel-png",
title: "Color Wheel PNG",
description:
"Generates an HSL color wheel: hue around the circle, saturation from center to edge, chosen lightness.",
category: "generate",
sourceMode: "none",
params: [
{
id: "width",
label: "Size",
type: "slider",
min: 128,
max: 1024,
step: 16,
default: 512,
},
{
id: "lightness",
label: "Lightness, %",
type: "slider",
min: 0,
max: 100,
step: 1,
default: 50,
},
],
generate: (p) =>
renderWheel(Math.trunc(num(p, "width")), num(p, "lightness")),
},
{
id: "complementary-png",
title: "Complementary Palette PNG",
description:
"Two opposite colors on the color wheel — the base and its complement.",
category: "generate",
sourceMode: "none",
params: paletteParams("#2563eb"),
generate: (p) =>
renderSwatches(
complementarySet(str(p, "baseColor")),
num(p, "width"),
str(p, "layout") as "strip" | "grid",
),
},
{
id: "triadic-png",
title: "Triadic Palette PNG",
description: "Three colors evenly spaced 120° apart on the color wheel.",
category: "generate",
sourceMode: "none",
params: paletteParams("#ff0000"),
generate: (p) =>
renderSwatches(
triadicSet(str(p, "baseColor")),
num(p, "width"),
str(p, "layout") as "strip" | "grid",
),
},
{
id: "tetradic-png",
title: "Tetradic Palette PNG",
description:
"Four colors in two complementary pairs, 90° apart on the wheel.",
category: "generate",
sourceMode: "none",
params: paletteParams("#8000ff"),
generate: (p) =>
renderSwatches(
tetradicSet(str(p, "baseColor")),
num(p, "width"),
str(p, "layout") as "strip" | "grid",
),
},
{
id: "analogous-png",
title: "Analogous Palette PNG",
description:
"Neighboring hues around the base color — calm, related color scheme.",
category: "generate",
sourceMode: "none",
params: [
...paletteParams("#22c55e"),
{
id: "spread",
label: "Hue spread, °",
type: "slider",
min: 10,
max: 90,
step: 5,
default: 30,
},
{
id: "count",
label: "Colors",
type: "slider",
min: 3,
max: 9,
step: 1,
default: 5,
},
],
generate: (p) =>
renderSwatches(
analogousSet(str(p, "baseColor"), num(p, "spread"), num(p, "count")),
num(p, "width"),
str(p, "layout") as "strip" | "grid",
),
},
{
id: "monochromatic-png",
title: "Monochromatic Palette PNG",
description:
"Tones of a single hue: lightness varies within the chosen range, hue and saturation stay fixed.",
category: "generate",
sourceMode: "none",
params: [
...paletteParams("#0ea5e9"),
{
id: "count",
label: "Colors",
type: "slider",
min: 2,
max: 9,
step: 1,
default: 5,
},
{
id: "range",
label: "Lightness range, %",
type: "slider",
min: 10,
max: 90,
step: 5,
default: 40,
},
],
generate: (p) =>
renderSwatches(
monochromaticSet(
str(p, "baseColor"),
num(p, "count"),
num(p, "range"),
),
num(p, "width"),
str(p, "layout") as "strip" | "grid",
),
},
{
id: "shades-png",
title: "Shade Ramp PNG",
description: "A ramp of the base color getting darker step by step.",
category: "generate",
sourceMode: "none",
params: [
...paletteParams("#f59e0b"),
{
id: "count",
label: "Colors",
type: "slider",
min: 2,
max: 9,
step: 1,
default: 5,
},
{
id: "depth",
label: "Darkening depth, %",
type: "slider",
min: 10,
max: 90,
step: 5,
default: 50,
},
],
generate: (p) =>
renderSwatches(
shadeSet(str(p, "baseColor"), num(p, "count"), num(p, "depth")),
num(p, "width"),
str(p, "layout") as "strip" | "grid",
),
},
{
id: "mix-colors-png",
title: "Mix Colors PNG",
description:
"Averages several hex colors into one swatch. Enter comma-separated #hex values; invalid tokens are skipped.",
category: "generate",
sourceMode: "none",
params: [
{
id: "colors",
label: "Colors (comma-separated hex)",
type: "text",
default: "#ff0000,#00ff00,#0000ff",
},
{
id: "width",
label: "Width",
type: "slider",
min: 128,
max: 1024,
step: 16,
default: 512,
},
],
generate: (p) =>
renderSwatches(
[mixColors(parseHexList(str(p, "colors")))],
num(p, "width"),
"strip",
),
},
{
id: "blend-two-png",
title: "Blend Two Colors PNG",
description: "A continuous horizontal gradient between two colors.",
category: "generate",
sourceMode: "none",
params: [
{
id: "colorA",
label: "Color A",
type: "color",
default: "#000000",
},
{
id: "colorB",
label: "Color B",
type: "color",
default: "#ffffff",
},
{
id: "width",
label: "Width",
type: "slider",
min: 128,
max: 1024,
step: 16,
default: 512,
},
],
generate: (p) =>
renderBlend(str(p, "colorA"), str(p, "colorB"), num(p, "width")),
},
{
id: "step-colors-png",
title: "Color Steps PNG",
description: "A discrete set of evenly spaced steps between two colors.",
category: "generate",
sourceMode: "none",
params: [
{
id: "colorA",
label: "Color A",
type: "color",
default: "#000000",
},
{
id: "colorB",
label: "Color B",
type: "color",
default: "#ffffff",
},
{
id: "steps",
label: "Steps",
type: "slider",
min: 2,
max: 12,
step: 1,
default: 6,
},
...paletteParams("#808080").filter((q) => q.id !== "baseColor"),
],
generate: (p) =>
renderSwatches(
stepColors(str(p, "colorA"), str(p, "colorB"), num(p, "steps")),
num(p, "width"),
str(p, "layout") as "strip" | "grid",
),
},
{
id: "sort-colors-png",
title: "Sort Colors PNG",
description:
"Renders your hex list as swatches sorted by hue, brightness or saturation. Invalid tokens are skipped.",
category: "generate",
sourceMode: "none",
params: [
{
id: "colors",
label: "Colors (comma-separated hex)",
type: "text",
default: "#ff0000,#ff8800,#ffff00,#00cc44,#0066ff,#8800ff",
},
{
id: "order",
label: "Sort by",
type: "select",
default: "hue",
options: [
{ value: "hue", label: "Hue" },
{ value: "luma", label: "Brightness" },
{ value: "sat", label: "Saturation" },
],
},
...paletteParams("#ffffff").filter((q) => q.id !== "baseColor"),
],
generate: (p) =>
renderSwatches(
sortPalette(
parseHexList(str(p, "colors")),
str(p, "order") as SortKey,
),
num(p, "width"),
str(p, "layout") as "strip" | "grid",
),
},
];
}