openpencil/packages/core/src/tools/describe-shared.ts
Anton A S d688d04bef Address PR #94 review: dedup, replace hand-rolled code, cleanup
- Replace calc.ts (150 lines) with expr-eval library
- Replace rgbLuminance with culori wcagLuminance
- Use @iconify/utils iconToSVG for viewBox normalization in iconify.ts
- Extract describe-shared.ts: findAncestorBackground, looksLikeButton, CONTAINER_TYPES
- Extract icon-render.ts: shared createIconFromPaths for create.ts and renderer.ts
- Inline codegen prompt as TS constant, remove runtime fs.readFile from MCP server
- Fix blur effect color alpha (a:1 → a:0)
- Encapsulate module-level mutable state in src/ai/tools.ts into RunState class
- Add network check to iconify tests (skip gracefully offline)
- Remove Caddyfile.dev and components.d.ts from tracking, add to .gitignore
2026-03-13 14:46:18 +03:00

28 lines
1.1 KiB
TypeScript

import type { Color } from '../types'
import type { SceneGraph, SceneNode } from '../scene-graph'
export const CONTAINER_TYPES = new Set(['FRAME', 'COMPONENT', 'INSTANCE'])
export const BUTTON_MAX_WIDTH = 200
export const BUTTON_MAX_HEIGHT = 50
export const BUTTON_MIN_HEIGHT = 28
export const BUTTON_MIN_RADIUS = 2
export function findAncestorBackground(node: SceneNode, graph: SceneGraph): Color | null {
let current = node.parentId ? graph.getNode(node.parentId) : null
while (current) {
const solidFill = current.fills.find((f) => f.visible && f.type === 'SOLID' && f.opacity > 0.5)
if (solidFill) return solidFill.color
current = current.parentId ? graph.getNode(current.parentId) : null
}
return null
}
export function looksLikeButton(node: SceneNode): boolean {
if (!CONTAINER_TYPES.has(node.type)) return false
if (node.width > BUTTON_MAX_WIDTH || node.height > BUTTON_MAX_HEIGHT || node.height < BUTTON_MIN_HEIGHT) return false
if (node.fills.length === 0 && node.strokes.length === 0) return false
if (node.cornerRadius < BUTTON_MIN_RADIUS) return false
return node.childIds.length > 0
}