mirror of
https://github.com/penpot/penpot-mcp.git
synced 2026-04-25 11:18:37 +00:00
PenpotUtils.shapeStructure: Add essential information on layouts #26
This commit is contained in:
parent
4353f67322
commit
3c1bd875d8
@ -32,12 +32,12 @@ initial_instructions: |
|
||||
A `Group` is a more low-level grouping element used to organize low-level shapes into a logical unit.
|
||||
Actual low-level shape types are `Rectangle`, `Path`, `Text`, `Ellipse`, `Image`, `Boolean`, and `SvgRaw`.
|
||||
`ShapeBase` is a base type most shapes build upon.
|
||||
|
||||
|
||||
## Core Shape Properties
|
||||
|
||||
|
||||
**Type**:
|
||||
Any given shape contains information on the concrete type via its `type` field.
|
||||
|
||||
|
||||
**Position and Dimensions**:
|
||||
* The location properties `x` and `y` refer to the top left corner of a shape's bounding box in the absolute (Page) coordinate system.
|
||||
These are writable - set them directly to position shapes.
|
||||
@ -45,24 +45,24 @@ initial_instructions: |
|
||||
To position a shape within its parent, set the absolute `x` and `y` properties accordingly.
|
||||
* `width` and `height` are READ-ONLY. Use `resize(width, height)` method to change dimensions.
|
||||
* `bounds` is a READ-ONLY property. Use `x`, `y` with `resize()` to modify shape bounds.
|
||||
|
||||
|
||||
**Other Writable Properties**:
|
||||
* `name` - Shape name
|
||||
* `fills`, `strokes` - Styling properties
|
||||
* `rotation`, `opacity`, `blocked`, `hidden`, `visible`
|
||||
|
||||
|
||||
**Z-Order**:
|
||||
* The z-order of shapes is determined by the order in the `children` array of the parent shape.
|
||||
Therefore, when creating shapes that should be on top of each other, add them to the parent in the correct order
|
||||
(i.e. add background shapes first, then foreground shapes later).
|
||||
* To modify z-order after creation, use these methods: `bringToFront()`, `sendToBack()`, `bringForward()`, `sendBackward()`,
|
||||
and, for precise control, `setParentIndex(index)` (0-based).
|
||||
|
||||
|
||||
**Modification Methods**:
|
||||
* `resize(width, height)` - Change dimensions (required for width/height since they're read-only)
|
||||
* `rotate(angle, center?)` - Rotate shape
|
||||
* `remove()` - Permanently destroy the shape (use only for deletion, NOT for reparenting)
|
||||
|
||||
|
||||
**Reparenting (Moving Shapes Between Parents)**:
|
||||
* `newParent.appendChild(shape)` or `newParent.insertChild(index, shape)` - Move shape to new parent
|
||||
- Automatically removes the shape from its old parent
|
||||
@ -70,18 +70,18 @@ initial_instructions: |
|
||||
- You may need to adjust absolute x/y after reparenting to achieve desired visual layout
|
||||
|
||||
# Images
|
||||
|
||||
|
||||
The `Image` type is a legacy type. Images are now typically mostly embedded in a `Fill` with `fillImage` set to an
|
||||
`ImageData` object, i.e. the `fills` property of of a shape (e.g. a `Rectangle`) will contain a fill where `fillImage` is set.
|
||||
|
||||
|
||||
# Visual Inspection of Designs
|
||||
|
||||
For many tasks, it can be critical to visually inspect the design. Remember to use the `export_shape` tool for this purpose!
|
||||
|
||||
|
||||
# Layout Systems
|
||||
|
||||
Boards can have layout systems that automatically control the positioning and spacing of their children:
|
||||
|
||||
|
||||
* **Flex Layout**: `board.flex` - A flexbox-style layout system
|
||||
- Properties: `dir` (direction), `rowGap`, `columnGap`, `alignItems`, `justifyContent`
|
||||
- Padding: `topPadding`, `rightPadding`, `bottomPadding`, `leftPadding`, or combined `verticalPadding`, `horizontalPadding`
|
||||
@ -102,7 +102,7 @@ initial_instructions: |
|
||||
# Semantic Containment vs Hierarchical Nesting
|
||||
|
||||
Understanding the difference between hierarchical structure and visual containment is critical:
|
||||
|
||||
|
||||
* **Hierarchical nesting** (parent/child in the shape tree) does NOT always equal **visual containment**
|
||||
* Visual containment means a child shape is fully within the visual bounds of its parent
|
||||
* Common design patterns require semantic containment:
|
||||
@ -147,9 +147,10 @@ initial_instructions: |
|
||||
* getPages(): { id: string; name: string }[]
|
||||
* getPageById(id: string): Page | null
|
||||
* getPageByName(name: string): Page | null
|
||||
* shapeStructure(shape: Shape, maxDepth: number | undefined = undefined): object
|
||||
Generates an overview structure of the given shape,
|
||||
providing the shape's id, name and type, and recursively the children's structure.
|
||||
* shapeStructure(shape: Shape, maxDepth: number | undefined = undefined): { id, name, type, children?, layout? }
|
||||
Generates an overview structure of the given shape.
|
||||
- children: recursive, limited by maxDepth
|
||||
- layout: present if shape has flex/grid layout, contains { type: "flex" | "grid", ... }
|
||||
* findShapeById(id: string): Shape | null
|
||||
* findShape(predicate: (shape: Shape) => boolean, root: Shape | null = null): Shape | null
|
||||
If no root is provided, search globally (in all pages).
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { Fill, Page, Rectangle, Shape } from "@penpot/plugin-types";
|
||||
import { Fill, FlexLayout, GridLayout, Page, Rectangle, Shape } from "@penpot/plugin-types";
|
||||
|
||||
export class PenpotUtils {
|
||||
/**
|
||||
* Generates an overview structure of the given shape,
|
||||
* providing its id, name and type, and recursively its children's attributes.
|
||||
* The `type` field indicates the type in the Penpot API.
|
||||
* If the shape has a layout system (flex or grid), includes layout information.
|
||||
*
|
||||
* @param shape - The root shape to generate the structure from
|
||||
* @param maxDepth - Optional maximum depth to traverse (leave undefined for unlimited)
|
||||
@ -19,12 +20,35 @@ export class PenpotUtils {
|
||||
);
|
||||
}
|
||||
}
|
||||
return {
|
||||
|
||||
const result: any = {
|
||||
id: shape.id,
|
||||
name: shape.name,
|
||||
type: shape.type,
|
||||
children: children,
|
||||
};
|
||||
|
||||
// add layout information if present
|
||||
if ("flex" in shape && shape.flex) {
|
||||
const flex: FlexLayout = shape.flex;
|
||||
result.layout = {
|
||||
type: "flex",
|
||||
dir: flex.dir,
|
||||
rowGap: flex.rowGap,
|
||||
columnGap: flex.columnGap,
|
||||
};
|
||||
} else if ("grid" in shape && shape.grid) {
|
||||
const grid: GridLayout = shape.grid;
|
||||
result.layout = {
|
||||
type: "grid",
|
||||
rows: grid.rows,
|
||||
columns: grid.columns,
|
||||
rowGap: grid.rowGap,
|
||||
columnGap: grid.columnGap,
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user