mirror of
https://github.com/github/awesome-copilot.git
synced 2026-02-24 04:15:14 +00:00
feat(skills): add excalidraw-diagram-generator skill and docs update
This commit is contained in:
497
skills/excalidraw-diagram-generator/references/element-types.md
Normal file
497
skills/excalidraw-diagram-generator/references/element-types.md
Normal file
@@ -0,0 +1,497 @@
|
||||
# Excalidraw Element Types Guide
|
||||
|
||||
Detailed specifications for each Excalidraw element type with visual examples and use cases.
|
||||
|
||||
## Element Type Overview
|
||||
|
||||
| Type | Visual | Primary Use | Text Support |
|
||||
|------|--------|-------------|--------------|
|
||||
| `rectangle` | □ | Boxes, containers, process steps | ✅ Yes |
|
||||
| `ellipse` | ○ | Emphasis, terminals, states | ✅ Yes |
|
||||
| `diamond` | ◇ | Decision points, choices | ✅ Yes |
|
||||
| `arrow` | → | Directional flow, relationships | ❌ No (use separate text) |
|
||||
| `line` | — | Connections, dividers | ❌ No |
|
||||
| `text` | A | Labels, annotations, titles | ✅ (Its purpose) |
|
||||
|
||||
---
|
||||
|
||||
## Rectangle
|
||||
|
||||
**Best for:** Process steps, entities, data stores, components
|
||||
|
||||
### Properties
|
||||
|
||||
```typescript
|
||||
{
|
||||
type: "rectangle",
|
||||
roundness: { type: 3 }, // Rounded corners
|
||||
text: "Step Name", // Optional embedded text
|
||||
fontSize: 20,
|
||||
textAlign: "center",
|
||||
verticalAlign: "middle"
|
||||
}
|
||||
```
|
||||
|
||||
### Use Cases
|
||||
|
||||
| Scenario | Configuration |
|
||||
|----------|---------------|
|
||||
| **Process step** | Green background (`#b2f2bb`), centered text |
|
||||
| **Entity/Object** | Blue background (`#a5d8ff`), medium size |
|
||||
| **System component** | Light color, descriptive text |
|
||||
| **Data store** | Gray/white, database-like label |
|
||||
|
||||
### Size Guidelines
|
||||
|
||||
| Content | Width | Height |
|
||||
|---------|-------|--------|
|
||||
| Single word | 120-150px | 60-80px |
|
||||
| Short phrase (2-4 words) | 180-220px | 80-100px |
|
||||
| Sentence | 250-300px | 100-120px |
|
||||
|
||||
### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "rectangle",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 200,
|
||||
"height": 80,
|
||||
"backgroundColor": "#b2f2bb",
|
||||
"text": "Validate Input",
|
||||
"fontSize": 20,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"roundness": { "type": 3 }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Ellipse
|
||||
|
||||
**Best for:** Start/end points, states, emphasis circles
|
||||
|
||||
### Properties
|
||||
|
||||
```typescript
|
||||
{
|
||||
type: "ellipse",
|
||||
text: "Start",
|
||||
fontSize: 18,
|
||||
textAlign: "center",
|
||||
verticalAlign: "middle"
|
||||
}
|
||||
```
|
||||
|
||||
### Use Cases
|
||||
|
||||
| Scenario | Configuration |
|
||||
|----------|---------------|
|
||||
| **Flow start** | Light green, "Start" text |
|
||||
| **Flow end** | Light red, "End" text |
|
||||
| **State** | Soft color, state name |
|
||||
| **Highlight** | Bright color, emphasis text |
|
||||
|
||||
### Size Guidelines
|
||||
|
||||
For circular shapes, use `width === height`:
|
||||
|
||||
| Content | Diameter |
|
||||
|---------|----------|
|
||||
| Icon/Symbol | 60-80px |
|
||||
| Short text | 100-120px |
|
||||
| Longer text | 150-180px |
|
||||
|
||||
### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "ellipse",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 120,
|
||||
"height": 120,
|
||||
"backgroundColor": "#d0f0c0",
|
||||
"text": "Start",
|
||||
"fontSize": 18,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Diamond
|
||||
|
||||
**Best for:** Decision points, conditional branches
|
||||
|
||||
### Properties
|
||||
|
||||
```typescript
|
||||
{
|
||||
type: "diamond",
|
||||
text: "Valid?",
|
||||
fontSize: 18,
|
||||
textAlign: "center",
|
||||
verticalAlign": "middle"
|
||||
}
|
||||
```
|
||||
|
||||
### Use Cases
|
||||
|
||||
| Scenario | Text Example |
|
||||
|----------|--------------|
|
||||
| **Yes/No decision** | "Is Valid?", "Exists?" |
|
||||
| **Multiple choice** | "Type?", "Status?" |
|
||||
| **Conditional** | "Score > 50?" |
|
||||
|
||||
### Size Guidelines
|
||||
|
||||
Diamonds need more space than rectangles for the same text:
|
||||
|
||||
| Content | Width | Height |
|
||||
|---------|-------|--------|
|
||||
| Yes/No | 120-140px | 120-140px |
|
||||
| Short question | 160-180px | 160-180px |
|
||||
| Longer question | 200-220px | 200-220px |
|
||||
|
||||
### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "diamond",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 150,
|
||||
"height": 150,
|
||||
"backgroundColor": "#ffe4a3",
|
||||
"text": "Valid?",
|
||||
"fontSize": 18,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Arrow
|
||||
|
||||
**Best for:** Flow direction, relationships, dependencies
|
||||
|
||||
### Properties
|
||||
|
||||
```typescript
|
||||
{
|
||||
type: "arrow",
|
||||
points: [[0, 0], [endX, endY]], // Relative coordinates
|
||||
roundness: { type: 2 }, // Curved
|
||||
startBinding: null, // Or { elementId, focus, gap }
|
||||
endBinding: null
|
||||
}
|
||||
```
|
||||
|
||||
### Arrow Directions
|
||||
|
||||
#### Horizontal (Left to Right)
|
||||
|
||||
```json
|
||||
{
|
||||
"x": 100,
|
||||
"y": 150,
|
||||
"width": 200,
|
||||
"height": 0,
|
||||
"points": [[0, 0], [200, 0]]
|
||||
}
|
||||
```
|
||||
|
||||
#### Vertical (Top to Bottom)
|
||||
|
||||
```json
|
||||
{
|
||||
"x": 200,
|
||||
"y": 100,
|
||||
"width": 0,
|
||||
"height": 150,
|
||||
"points": [[0, 0], [0, 150]]
|
||||
}
|
||||
```
|
||||
|
||||
#### Diagonal
|
||||
|
||||
```json
|
||||
{
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 200,
|
||||
"height": 150,
|
||||
"points": [[0, 0], [200, 150]]
|
||||
}
|
||||
```
|
||||
|
||||
### Arrow Styles
|
||||
|
||||
| Style | `strokeStyle` | `strokeWidth` | Use Case |
|
||||
|-------|---------------|---------------|----------|
|
||||
| **Normal flow** | `"solid"` | 2 | Standard connections |
|
||||
| **Optional/Weak** | `"dashed"` | 2 | Optional paths |
|
||||
| **Important** | `"solid"` | 3-4 | Emphasized flow |
|
||||
| **Dotted** | `"dotted"` | 2 | Indirect relationships |
|
||||
|
||||
### Adding Arrow Labels
|
||||
|
||||
Use separate text elements positioned near arrow midpoint:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "arrow",
|
||||
"id": "arrow1",
|
||||
"x": 100,
|
||||
"y": 150,
|
||||
"points": [[0, 0], [200, 0]]
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"x": 180, // Near midpoint
|
||||
"y": 130, // Above arrow
|
||||
"text": "sends",
|
||||
"fontSize": 14
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Line
|
||||
|
||||
**Best for:** Non-directional connections, dividers, borders
|
||||
|
||||
### Properties
|
||||
|
||||
```typescript
|
||||
{
|
||||
type: "line",
|
||||
points: [[0, 0], [x2, y2], [x3, y3], ...],
|
||||
roundness: null // Or { type: 2 } for curved
|
||||
}
|
||||
```
|
||||
|
||||
### Use Cases
|
||||
|
||||
| Scenario | Configuration |
|
||||
|----------|---------------|
|
||||
| **Divider** | Horizontal, thin stroke |
|
||||
| **Border** | Closed path (polygon) |
|
||||
| **Connection** | Multi-point path |
|
||||
| **Underline** | Short horizontal line |
|
||||
|
||||
### Multi-Point Line Example
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "line",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"points": [
|
||||
[0, 0],
|
||||
[100, 50],
|
||||
[200, 0]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Text
|
||||
|
||||
**Best for:** Labels, titles, annotations, standalone text
|
||||
|
||||
### Properties
|
||||
|
||||
```typescript
|
||||
{
|
||||
type: "text",
|
||||
text: "Label text",
|
||||
fontSize: 20,
|
||||
fontFamily: 1, // 1=Virgil, 2=Helvetica, 3=Cascadia
|
||||
textAlign: "left",
|
||||
verticalAlign: "top"
|
||||
}
|
||||
```
|
||||
|
||||
### Font Sizes by Purpose
|
||||
|
||||
| Purpose | Font Size |
|
||||
|---------|-----------|
|
||||
| **Main title** | 28-36 |
|
||||
| **Section header** | 24-28 |
|
||||
| **Element label** | 18-22 |
|
||||
| **Annotation** | 14-16 |
|
||||
| **Small note** | 12-14 |
|
||||
|
||||
### Width/Height Calculation
|
||||
|
||||
```javascript
|
||||
// Approximate width
|
||||
const width = text.length * fontSize * 0.6;
|
||||
|
||||
// Approximate height (single line)
|
||||
const height = fontSize * 1.2;
|
||||
|
||||
// Multi-line
|
||||
const lines = text.split('\n').length;
|
||||
const height = fontSize * 1.2 * lines;
|
||||
```
|
||||
|
||||
### Text Positioning
|
||||
|
||||
| Position | textAlign | verticalAlign | Use Case |
|
||||
|----------|-----------|---------------|----------|
|
||||
| **Top-left** | `"left"` | `"top"` | Default labels |
|
||||
| **Centered** | `"center"` | `"middle"` | Titles |
|
||||
| **Bottom-right** | `"right"` | `"bottom"` | Footnotes |
|
||||
|
||||
### Example: Title
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "text",
|
||||
"x": 100,
|
||||
"y": 50,
|
||||
"width": 400,
|
||||
"height": 40,
|
||||
"text": "System Architecture",
|
||||
"fontSize": 32,
|
||||
"fontFamily": 2,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "top"
|
||||
}
|
||||
```
|
||||
|
||||
### Example: Annotation
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "text",
|
||||
"x": 150,
|
||||
"y": 200,
|
||||
"width": 100,
|
||||
"height": 20,
|
||||
"text": "User input",
|
||||
"fontSize": 14,
|
||||
"fontFamily": 1,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Combining Elements
|
||||
|
||||
### Pattern: Labeled Box
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "rectangle",
|
||||
"id": "box1",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 200,
|
||||
"height": 100,
|
||||
"text": "Component",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Pattern: Connected Boxes
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "rectangle",
|
||||
"id": "box1",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 150,
|
||||
"height": 80,
|
||||
"text": "Step 1"
|
||||
},
|
||||
{
|
||||
"type": "arrow",
|
||||
"id": "arrow1",
|
||||
"x": 250,
|
||||
"y": 140,
|
||||
"points": [[0, 0], [100, 0]]
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"id": "box2",
|
||||
"x": 350,
|
||||
"y": 100,
|
||||
"width": 150,
|
||||
"height": 80,
|
||||
"text": "Step 2"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Pattern: Decision Tree
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "diamond",
|
||||
"id": "decision",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 140,
|
||||
"height": 140,
|
||||
"text": "Valid?"
|
||||
},
|
||||
{
|
||||
"type": "arrow",
|
||||
"id": "yes-arrow",
|
||||
"x": 240,
|
||||
"y": 170,
|
||||
"points": [[0, 0], [60, 0]]
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"id": "yes-label",
|
||||
"x": 250,
|
||||
"y": 150,
|
||||
"text": "Yes",
|
||||
"fontSize": 14
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"id": "yes-box",
|
||||
"x": 300,
|
||||
"y": 140,
|
||||
"width": 120,
|
||||
"height": 60,
|
||||
"text": "Process"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| When you need... | Use this element |
|
||||
|------------------|------------------|
|
||||
| Process box | `rectangle` with text |
|
||||
| Decision point | `diamond` with question |
|
||||
| Flow direction | `arrow` |
|
||||
| Start/End | `ellipse` |
|
||||
| Title/Header | `text` (large font) |
|
||||
| Annotation | `text` (small font) |
|
||||
| Non-directional link | `line` |
|
||||
| Divider | `line` (horizontal) |
|
||||
@@ -0,0 +1,350 @@
|
||||
# Excalidraw JSON Schema Reference
|
||||
|
||||
This document describes the structure of Excalidraw `.excalidraw` files for diagram generation.
|
||||
|
||||
## Top-Level Structure
|
||||
|
||||
```typescript
|
||||
interface ExcalidrawFile {
|
||||
type: "excalidraw";
|
||||
version: number; // Always 2
|
||||
source: string; // "https://excalidraw.com"
|
||||
elements: ExcalidrawElement[];
|
||||
appState: AppState;
|
||||
files: Record<string, any>; // Usually empty {}
|
||||
}
|
||||
```
|
||||
|
||||
## AppState
|
||||
|
||||
```typescript
|
||||
interface AppState {
|
||||
viewBackgroundColor: string; // Hex color, e.g., "#ffffff"
|
||||
gridSize: number; // Typically 20
|
||||
}
|
||||
```
|
||||
|
||||
## ExcalidrawElement Base Properties
|
||||
|
||||
All elements share these common properties:
|
||||
|
||||
```typescript
|
||||
interface BaseElement {
|
||||
id: string; // Unique identifier
|
||||
type: ElementType; // See Element Types below
|
||||
x: number; // X coordinate (pixels from top-left)
|
||||
y: number; // Y coordinate (pixels from top-left)
|
||||
width: number; // Width in pixels
|
||||
height: number; // Height in pixels
|
||||
angle: number; // Rotation angle in radians (usually 0)
|
||||
strokeColor: string; // Hex color, e.g., "#1e1e1e"
|
||||
backgroundColor: string; // Hex color or "transparent"
|
||||
fillStyle: "solid" | "hachure" | "cross-hatch";
|
||||
strokeWidth: number; // 1-4 typically
|
||||
strokeStyle: "solid" | "dashed" | "dotted";
|
||||
roughness: number; // 0-2, controls hand-drawn effect (1 = default)
|
||||
opacity: number; // 0-100
|
||||
groupIds: string[]; // IDs of groups this element belongs to
|
||||
frameId: null; // Usually null
|
||||
index: string; // Stacking order identifier
|
||||
roundness: Roundness | null;
|
||||
seed: number; // Random seed for deterministic rendering
|
||||
version: number; // Element version (increment on edit)
|
||||
versionNonce: number; // Random number changed on edit
|
||||
isDeleted: boolean; // Should be false
|
||||
boundElements: any; // Usually null
|
||||
updated: number; // Timestamp in milliseconds
|
||||
link: null; // External link (usually null)
|
||||
locked: boolean; // Whether element is locked
|
||||
}
|
||||
```
|
||||
|
||||
## Element Types
|
||||
|
||||
### Rectangle
|
||||
|
||||
```typescript
|
||||
interface RectangleElement extends BaseElement {
|
||||
type: "rectangle";
|
||||
roundness: { type: 3 }; // 3 = rounded corners
|
||||
text?: string; // Optional text inside
|
||||
fontSize?: number; // Font size (16-32 typical)
|
||||
fontFamily?: number; // 1 = Virgil, 2 = Helvetica, 3 = Cascadia
|
||||
textAlign?: "left" | "center" | "right";
|
||||
verticalAlign?: "top" | "middle" | "bottom";
|
||||
}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"id": "rect1",
|
||||
"type": "rectangle",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 200,
|
||||
"height": 100,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#a5d8ff",
|
||||
"text": "My Box",
|
||||
"fontSize": 20,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"roundness": { "type": 3 }
|
||||
}
|
||||
```
|
||||
|
||||
### Ellipse
|
||||
|
||||
```typescript
|
||||
interface EllipseElement extends BaseElement {
|
||||
type: "ellipse";
|
||||
text?: string;
|
||||
fontSize?: number;
|
||||
fontFamily?: number;
|
||||
textAlign?: "left" | "center" | "right";
|
||||
verticalAlign?: "top" | "middle" | "bottom";
|
||||
}
|
||||
```
|
||||
|
||||
### Diamond
|
||||
|
||||
```typescript
|
||||
interface DiamondElement extends BaseElement {
|
||||
type: "diamond";
|
||||
text?: string;
|
||||
fontSize?: number;
|
||||
fontFamily?: number;
|
||||
textAlign?: "left" | "center" | "right";
|
||||
verticalAlign?: "top" | "middle" | "bottom";
|
||||
}
|
||||
```
|
||||
|
||||
### Arrow
|
||||
|
||||
```typescript
|
||||
interface ArrowElement extends BaseElement {
|
||||
type: "arrow";
|
||||
points: [number, number][]; // Array of [x, y] coordinates relative to element
|
||||
startBinding: Binding | null;
|
||||
endBinding: Binding | null;
|
||||
roundness: { type: 2 }; // 2 = curved arrow
|
||||
}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"id": "arrow1",
|
||||
"type": "arrow",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 200,
|
||||
"height": 0,
|
||||
"points": [
|
||||
[0, 0],
|
||||
[200, 0]
|
||||
],
|
||||
"roundness": { "type": 2 },
|
||||
"startBinding": null,
|
||||
"endBinding": null
|
||||
}
|
||||
```
|
||||
|
||||
**Points explanation:**
|
||||
- First point `[0, 0]` is relative to `(x, y)`
|
||||
- Subsequent points are relative to the first point
|
||||
- For straight horizontal arrow: `[[0, 0], [width, 0]]`
|
||||
- For straight vertical arrow: `[[0, 0], [0, height]]`
|
||||
|
||||
### Line
|
||||
|
||||
```typescript
|
||||
interface LineElement extends BaseElement {
|
||||
type: "line";
|
||||
points: [number, number][];
|
||||
startBinding: Binding | null;
|
||||
endBinding: Binding | null;
|
||||
roundness: { type: 2 } | null;
|
||||
}
|
||||
```
|
||||
|
||||
### Text
|
||||
|
||||
```typescript
|
||||
interface TextElement extends BaseElement {
|
||||
type: "text";
|
||||
text: string;
|
||||
fontSize: number;
|
||||
fontFamily: number; // 1-3
|
||||
textAlign: "left" | "center" | "right";
|
||||
verticalAlign: "top" | "middle" | "bottom";
|
||||
roundness: null; // Text has no roundness
|
||||
}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"id": "text1",
|
||||
"type": "text",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 150,
|
||||
"height": 25,
|
||||
"text": "Hello World",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 1,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"roundness": null
|
||||
}
|
||||
```
|
||||
|
||||
**Width/Height calculation:**
|
||||
- Width ≈ `text.length * fontSize * 0.6`
|
||||
- Height ≈ `fontSize * 1.2 * numberOfLines`
|
||||
|
||||
## Bindings
|
||||
|
||||
Bindings connect arrows to shapes:
|
||||
|
||||
```typescript
|
||||
interface Binding {
|
||||
elementId: string; // ID of bound element
|
||||
focus: number; // -1 to 1, position along edge
|
||||
gap: number; // Distance from element edge
|
||||
}
|
||||
```
|
||||
|
||||
## Common Colors
|
||||
|
||||
| Color Name | Hex Code | Use Case |
|
||||
|------------|----------|----------|
|
||||
| Black | `#1e1e1e` | Default stroke |
|
||||
| Light Blue | `#a5d8ff` | Primary entities |
|
||||
| Light Green | `#b2f2bb` | Process steps |
|
||||
| Yellow | `#ffd43b` | Important/Central |
|
||||
| Light Red | `#ffc9c9` | Warnings/Errors |
|
||||
| Cyan | `#96f2d7` | Secondary items |
|
||||
| Transparent | `transparent` | No fill |
|
||||
| White | `#ffffff` | Background |
|
||||
|
||||
## ID Generation
|
||||
|
||||
IDs should be unique strings. Common patterns:
|
||||
|
||||
```javascript
|
||||
// Timestamp-based
|
||||
const id = Date.now().toString(36) + Math.random().toString(36).substr(2);
|
||||
|
||||
// Sequential
|
||||
const id = "element-" + counter++;
|
||||
|
||||
// Descriptive
|
||||
const id = "step-1", "entity-user", "arrow-1-to-2";
|
||||
```
|
||||
|
||||
## Seed Generation
|
||||
|
||||
Seeds are used for deterministic randomness in hand-drawn effect:
|
||||
|
||||
```javascript
|
||||
const seed = Math.floor(Math.random() * 2147483647);
|
||||
```
|
||||
|
||||
## Version and VersionNonce
|
||||
|
||||
```javascript
|
||||
const version = 1; // Increment when element is edited
|
||||
const versionNonce = Math.floor(Math.random() * 2147483647);
|
||||
```
|
||||
|
||||
## Coordinate System
|
||||
|
||||
- Origin `(0, 0)` is top-left corner
|
||||
- X increases to the right
|
||||
- Y increases downward
|
||||
- All units are in pixels
|
||||
|
||||
## Recommended Spacing
|
||||
|
||||
| Context | Spacing |
|
||||
|---------|---------|
|
||||
| Horizontal gap between elements | 200-300px |
|
||||
| Vertical gap between rows | 100-150px |
|
||||
| Minimum margin from edge | 50px |
|
||||
| Arrow-to-box clearance | 20-30px |
|
||||
|
||||
## Font Families
|
||||
|
||||
| ID | Name | Description |
|
||||
|----|------|-------------|
|
||||
| 1 | Virgil | Hand-drawn style (default) |
|
||||
| 2 | Helvetica | Clean sans-serif |
|
||||
| 3 | Cascadia | Monospace |
|
||||
|
||||
## Validation Rules
|
||||
|
||||
✅ **Required:**
|
||||
- All IDs must be unique
|
||||
- `type` must match actual element type
|
||||
- `version` must be an integer ≥ 1
|
||||
- `opacity` must be 0-100
|
||||
|
||||
⚠️ **Recommended:**
|
||||
- Keep `roughness` at 1 for consistency
|
||||
- Use `strokeWidth` of 2 for clarity
|
||||
- Set `isDeleted` to `false`
|
||||
- Set `locked` to `false`
|
||||
- Keep `frameId`, `boundElements`, `link` as `null`
|
||||
|
||||
## Complete Minimal Example
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "https://excalidraw.com",
|
||||
"elements": [
|
||||
{
|
||||
"id": "box1",
|
||||
"type": "rectangle",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 200,
|
||||
"height": 100,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#a5d8ff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a0",
|
||||
"roundness": { "type": 3 },
|
||||
"seed": 1234567890,
|
||||
"version": 1,
|
||||
"versionNonce": 987654321,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1706659200000,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Hello",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 1,
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle"
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"gridSize": 20
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user