feat: add first-class text layers

This commit is contained in:
syntaxbullet
2026-07-11 12:38:34 +02:00
parent 606426c885
commit 37aa719047
33 changed files with 315 additions and 41 deletions

View File

@@ -1,4 +1,4 @@
import { FolderSimple, ImageBroken, SlidersHorizontal } from "@phosphor-icons/react";
import { FolderSimple, ImageBroken, SlidersHorizontal, TextT } from "@phosphor-icons/react";
import type { LayerThumbnailModel, RasterThumbnailModel } from "./thumbnailModel";
export function LayerThumbnail({ model, label, compact = false }: { model: LayerThumbnailModel; label: string; compact?: boolean }) {
@@ -16,6 +16,7 @@ export function LayerThumbnail({ model, label, compact = false }: { model: Layer
) : null}
{model.kind === "empty" ? <ImageBroken size={compact ? 14 : 17} className="text-white/35" /> : null}
{model.kind === "adjustment" ? <SlidersHorizontal size={compact ? 14 : 17} className="text-violet-200" /> : null}
{model.kind === "text" ? <TextT size={compact ? 14 : 17} style={{ color: model.color }} aria-label={model.content} /> : null}
</span>
);
}

View File

@@ -15,6 +15,7 @@ export type RasterThumbnailModel = {
export type LayerThumbnailModel =
| RasterThumbnailModel
| { kind: "adjustment" }
| { kind: "text"; content: string; color: string }
| { kind: "group"; previews: readonly RasterThumbnailModel[] }
| { kind: "empty" };
@@ -25,6 +26,7 @@ export function resolveLayerThumbnail(
excludedLayerIds: ReadonlySet<LayerId> = new Set(),
): LayerThumbnailModel {
if (layer.type === "adjustment") return { kind: "adjustment" };
if (layer.type === "text") return { kind: "text", content: layer.content, color: layer.style.color };
if (layer.type !== "group") return resolveRasterThumbnail(layer, assetById) ?? { kind: "empty" };
const previews: RasterThumbnailModel[] = [];
@@ -59,6 +61,7 @@ export function createLayerThumbnailIndex(
if (frame.visited || layer.type !== "group") {
if (layer.type !== "group") {
if (layer.type === "adjustment") { result.set(layer.id, { kind: "adjustment" }); continue; }
if (layer.type === "text") { result.set(layer.id, { kind: "text", content: layer.content, color: layer.style.color }); continue; }
result.set(layer.id, resolveRasterThumbnail(layer, assetById) ?? { kind: "empty" });
continue;
}
@@ -83,7 +86,7 @@ export function createLayerThumbnailIndex(
}
function resolveRasterThumbnail(layer: Exclude<Layer, { type: "group" }>, assetById: ReadonlyMap<AssetId, Asset>): RasterThumbnailModel | undefined {
if (layer.type === "adjustment") return undefined;
if (layer.type === "adjustment" || layer.type === "text") return undefined;
const asset = assetById.get(layer.assetId);
if (!asset || !asset.source.trim() || !positiveFinite(asset.intrinsicSize.w) || !positiveFinite(asset.intrinsicSize.h)) return undefined;