{"_id":"ai-figure","_rev":"12-3541d69d7e825d33ccdac8b77e535f8c","name":"ai-figure","dist-tags":{"latest":"1.0.0"},"versions":{"0.1.0":{"name":"ai-figure","version":"0.1.0","keywords":["flowchart","svg","diagram","dagre","excalidraw","sequence-diagram","architecture-diagram","tree-diagram"],"author":{"name":"hustcc"},"license":"MIT","_id":"ai-figure@0.1.0","maintainers":[{"name":"atool","email":"i@hust.cc"}],"dist":{"shasum":"3859e070e314facedfcb6056f595d560968f2467","tarball":"https://registry.npmjs.org/ai-figure/-/ai-figure-0.1.0.tgz","fileCount":16,"integrity":"sha512-8BIiF+/iKprdP4DbWhFxjrkundWNoW8jCf+UzlukUkYwQMuNXe3dT6LzouF5yxm3qhdDW8IYcPju2DyI9x7TBw==","signatures":[{"sig":"MEUCICh3i5Gkqyjb2n5YpWTuTuyIrP73cYU5NZskmNSimhwbAiEA1/WZltNgPwNwKYkDu1ti3WvwEGJaguG6lyGMwXOGkaQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2147800},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"eb776ebb4653288dd4b72b2290e660ee797c14b0","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"atool","email":"i@hust.cc"},"_npmVersion":"10.8.2","description":"Generate clean SVG diagrams (flowchart, tree, architecture, sequence) from a JSON config. Auto-layout, zero coordinates, works in browser and Node.js.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"dagre":"^0.8.5","d3-scale-chromatic":"^3.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^3.2.4","typescript":"^5.6.0","@types/node":"^22.0.0","@types/dagre":"^0.7.52","@types/d3-scale-chromatic":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ai-figure_0.1.0_1776562629278_0.9374897656916241","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"ai-figure","version":"0.2.0","keywords":["flowchart","svg","diagram","dagre","excalidraw","sequence-diagram","architecture-diagram","tree-diagram"],"author":{"name":"hustcc"},"license":"MIT","_id":"ai-figure@0.2.0","maintainers":[{"name":"atool","email":"i@hust.cc"}],"dist":{"shasum":"3738b09a70c054b06214b91ab44ebf5f8b8ae8be","tarball":"https://registry.npmjs.org/ai-figure/-/ai-figure-0.2.0.tgz","fileCount":16,"integrity":"sha512-PVvJDsQv5/PV5anPRv8gc+EB7uLDzX5SdYbjIe4hj5PdlYeRbhVcM6Vp70qbcVbLC7zlAzQCD/AY164hnI3ZhQ==","signatures":[{"sig":"MEUCIQDTeRddNITzcPZrL4Eqw4uvJ0DBMj7cTiKo8P4zgsSbmwIgAJuQx5OVvJGMYXj+y4nfaEMBg96j0iqilrgR+yKji18=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2289227},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"e5d027483fe6ff05909d82acb7c1d4c336486d61","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"atool","email":"i@hust.cc"},"_npmVersion":"10.8.2","description":"Generate clean SVG diagrams (flowchart, tree, architecture, sequence) from a JSON config. Auto-layout, zero coordinates, works in browser and Node.js.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"dagre":"^0.8.5"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^3.2.4","typescript":"^5.6.0","@types/node":"^22.0.0","@types/dagre":"^0.7.52"},"_npmOperationalInternal":{"tmp":"tmp/ai-figure_0.2.0_1776605008897_0.2758128980306629","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"ai-figure","version":"0.3.0","keywords":["flowchart","svg","diagram","dagre","excalidraw","sequence-diagram","architecture-diagram","tree-diagram"],"author":{"name":"hustcc"},"license":"MIT","_id":"ai-figure@0.3.0","maintainers":[{"name":"atool","email":"i@hust.cc"}],"dist":{"shasum":"02f06bbf1ac3b7586d6972d10f19cd5076efc80e","tarball":"https://registry.npmjs.org/ai-figure/-/ai-figure-0.3.0.tgz","fileCount":20,"integrity":"sha512-h/vRorXz5FDDiR4j1Sns67NpKA6TEDgkpJX4A3YrkYNASFAHzp3/TaRP8ROithQkyF+S/1qAyf8HW11kZc+rhw==","signatures":[{"sig":"MEUCIAluds9geVw57ySRs9hvAVzRJ4VfS3zEVzrWyPKiv3ITAiEA01iKur9ShpIgy5AB6JL/ZpmxFpEsmQ6F2jK5IUdYD6w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2559671},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"9bd6b6fac5b746dbd8142f3712fcd5e473e8cb76","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"atool","email":"i@hust.cc"},"_npmVersion":"10.8.2","description":"Generate clean SVG diagrams (flowchart, tree, architecture, sequence) from a JSON config. Auto-layout, zero coordinates, works in browser and Node.js.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"dagre":"^0.8.5"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^3.2.4","typescript":"^5.6.0","@types/node":"^22.0.0","@types/dagre":"^0.7.52"},"_npmOperationalInternal":{"tmp":"tmp/ai-figure_0.3.0_1776788847540_0.30387628663609445","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"ai-figure","version":"0.4.0","keywords":["flowchart","svg","diagram","dagre","excalidraw","sequence-diagram","architecture-diagram","tree-diagram"],"author":{"name":"hustcc"},"license":"MIT","_id":"ai-figure@0.4.0","maintainers":[{"name":"atool","email":"i@hust.cc"}],"dist":{"shasum":"cac8f1e771ca47154cc4ba7a626942a891c52e50","tarball":"https://registry.npmjs.org/ai-figure/-/ai-figure-0.4.0.tgz","fileCount":21,"integrity":"sha512-JCISlo/JxcmFB7DKM6WGW10hwFfwT1Q0pQTuN4z8bBw5kSMoZv6EH3sYQ1l/i/PstHjieba2jvtWFL+PqYRycg==","signatures":[{"sig":"MEQCIBLsctMaat28qtO84tTibLNpnGwzBu6lQ6D87DZGZodbAiAIJbra1PR7bIAvQ7cV7vu1eMX4F3ez9w6w4U1T9IGRZw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2631586},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"eb80b943690e177038c5117a43014717d20e38a3","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"atool","email":"i@hust.cc"},"_npmVersion":"10.8.2","description":"Generate clean SVG diagrams (flowchart, tree, architecture, sequence) from a JSON config. Auto-layout, zero coordinates, works in browser and Node.js.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"dagre":"^0.8.5"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^3.2.4","typescript":"^5.6.0","@types/node":"^22.0.0","@types/dagre":"^0.7.52"},"_npmOperationalInternal":{"tmp":"tmp/ai-figure_0.4.0_1777353442689_0.8570495493477066","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"ai-figure","version":"1.0.0","description":"Generate clean SVG diagrams (flowchart, tree, architecture, sequence) from a JSON config. Auto-layout, zero coordinates, works in browser and Node.js.","keywords":["flowchart","svg","diagram","dagre","excalidraw","sequence-diagram","architecture-diagram","tree-diagram"],"author":{"name":"hustcc"},"license":"MIT","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit"},"dependencies":{"dagre":"^0.8.5"},"devDependencies":{"@types/dagre":"^0.7.52","@types/node":"^22.0.0","tsup":"^8.3.0","typescript":"^5.6.0","vitest":"^3.2.4"},"repository":{"type":"git","url":"git+ssh://git@github.com/hustcc/ai-figure.git"},"gitHead":"9c2a51df0c85683569181c1ff6b22e2080345387","_id":"ai-figure@1.0.0","bugs":{"url":"https://github.com/hustcc/ai-figure/issues"},"homepage":"https://github.com/hustcc/ai-figure#readme","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-PNDzTbqWlgDRfI8WFrH313RNNsIDpInZq9xck8rbUurlDHxWE/1WifcmPws3d5Ar/eDBOiuKLUqb4HnHj9X6kw==","shasum":"212d1ec26ca5178b094aff9637aac0bef99084ed","tarball":"https://registry.npmjs.org/ai-figure/-/ai-figure-1.0.0.tgz","fileCount":25,"unpackedSize":3920080,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAW8esEZf2F4z7YEgEPFGuoDN5gKwaT2Oz4ZomCGVs71AiAPjCuvDEMF/6xKvN3VrsN7R8UUjsg2+bpKgyuavQUoBw=="}]},"_npmUser":{"name":"atool","email":"wzwahl36@qq.com"},"directories":{},"maintainers":[{"name":"atool","email":"wzwahl36@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ai-figure_1.0.0_1781178716957_0.6659323800667882"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-19T01:37:09.276Z","modified":"2026-06-11T11:51:57.242Z","0.1.0":"2026-04-19T01:37:09.433Z","0.2.0":"2026-04-19T13:23:29.116Z","0.3.0":"2026-04-21T16:27:27.736Z","0.4.0":"2026-04-28T05:17:22.849Z","0.5.0":"2026-05-19T01:56:42.843Z","0.6.0":"2026-05-19T02:06:00.421Z","1.0.0":"2026-06-11T11:51:57.130Z"},"author":{"name":"hustcc"},"license":"MIT","keywords":["flowchart","svg","diagram","dagre","excalidraw","sequence-diagram","architecture-diagram","tree-diagram"],"description":"Generate clean SVG diagrams (flowchart, tree, architecture, sequence) from a JSON config. Auto-layout, zero coordinates, works in browser and Node.js.","maintainers":[{"name":"atool","email":"wzwahl36@qq.com"}],"readme":"# [ai-figure](https://figure.ling.pub/gallery)\n\n> Clean SVG diagram renderer — define config, get beautiful diagrams. Works in browser **and** Node.js.\n\n[![npm version](https://img.shields.io/npm/v/ai-figure.svg)](https://www.npmjs.com/package/ai-figure)\n[![Build](https://github.com/hustcc/ai-figure/actions/workflows/build.yml/badge.svg)](https://github.com/hustcc/ai-figure/actions/workflows/build.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n<table>\n  <tr>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/flow.svg\" width=\"100%\" alt=\"Flowchart\"/>\n      <br/><small>Flowchart</small>\n    </td>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/tree.svg\" width=\"100%\" alt=\"Tree\"/>\n      <br/><small>Tree</small>\n    </td>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/arch.svg\" width=\"100%\" alt=\"Architecture\"/>\n      <br/><small>Architecture</small>\n    </td>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/sequence.svg\" width=\"100%\" alt=\"Sequence\"/>\n      <br/><small>Sequence</small>\n    </td>\n  </tr>\n  <tr>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/quadrant.svg\" width=\"100%\" alt=\"Quadrant\"/>\n      <br/><small>Quadrant</small>\n    </td>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/gantt.svg\" width=\"100%\" alt=\"Gantt\"/>\n      <br/><small>Gantt</small>\n    </td>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/state.svg\" width=\"100%\" alt=\"State Machine\"/>\n      <br/><small>State Machine</small>\n    </td>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/er.svg\" width=\"100%\" alt=\"ER Diagram\"/>\n      <br/><small>ER Diagram</small>\n    </td>\n  </tr>\n  <tr>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/mindmap.svg\" width=\"100%\" alt=\"Mindmap\"/>\n      <br/><small>Mindmap</small>\n      <br/>\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/timeline.svg\" width=\"100%\" alt=\"Timeline\"/>\n      <br/><small>Timeline</small>\n    </td>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/swimlane.svg\" width=\"100%\" alt=\"Swimlane\"/>\n      <br/><small>Swimlane</small>\n    </td>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/bubble.svg\" width=\"100%\" alt=\"Bubble Chart\"/>\n      <br/><small>Bubble Chart</small>\n    </td>\n    <td align=\"center\" width=\"25%\">\n      <img src=\"https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/radar.svg\" width=\"100%\" alt=\"Radar Chart\"/>\n      <br/><small>Radar Chart</small>\n    </td>\n  </tr>\n</table>\n\n## Features ✨\n\n- 🎨 **Rich visual styles** — light/dark mode, nine built-in palettes (`default`, `antv`, `drawio`, `figma`, `vega`, `mono-blue`, `mono-green`, `mono-purple`, `mono-orange`) plus custom hex arrays; every diagram supports optional title & subtitle, node groups, and color-coded layers\n- 📐 **Auto layout** — just describe the graph; x/y coordinates are computed automatically, and diagram dimensions scale to fit the content\n- 🤖 **AI-friendly** — single `fig()` entry point accepts a markdown string **or** a JSON config; streaming-safe (partial input never throws); ships a [`SKILL.md`](https://github.com/hustcc/ai-figure/blob/main/SKILL.md) that AI agents (Copilot, Cursor, Claude, etc.) can load as context\n- 📊 **13 diagram types** — flowchart, tree, mindmap, architecture, sequence, quadrant, Gantt, state machine, ER data model, timeline, swimlane, bubble chart, and radar chart; pure SVG output with zero DOM dependency, works in browser and Node.js\n\n## Quick Start\n\n### Install\n\n```bash\nnpm install ai-figure\n```\n\n### CDN (browser, no bundler)\n\n```html\n<!-- jsDelivr -->\n<script src=\"https://cdn.jsdelivr.net/npm/ai-figure/dist/index.global.js\"></script>\n\n<!-- unpkg -->\n<script src=\"https://unpkg.com/ai-figure/dist/index.global.js\"></script>\n```\n\nAfter loading the script, the library is available as the global `AiFigure`:\n\n```html\n<div id=\"chart\"></div>\n<script src=\"https://cdn.jsdelivr.net/npm/ai-figure/dist/index.global.js\"></script>\n<script>\n  const svg = AiFigure.fig(`\n    figure flow\n    direction: LR\n    start((Start)) --> login[Login]\n    login --> dashboard[Dashboard]\n  `);\n  document.getElementById('chart').innerHTML = svg;\n</script>\n```\n\n### Usage\n\n```typescript\nimport { fig } from 'ai-figure';\n\n// ── JSON config object (typed, programmatic) ────────────────────────────────\nconst svg = fig({\n  figure: 'flow',\n  nodes: [\n    { id: 'start',    label: 'Start',        type: 'terminal' },\n    { id: 'process1', label: 'Process Data', type: 'process'  },\n    { id: 'decision', label: 'Is Valid?',    type: 'decision' },\n    { id: 'end_yes',  label: 'Success',      type: 'terminal' },\n    { id: 'end_no',   label: 'Failure',      type: 'terminal' },\n  ],\n  edges: [\n    { from: 'start',    to: 'process1'              },\n    { from: 'process1', to: 'decision'              },\n    { from: 'decision', to: 'end_yes', label: 'Yes' },\n    { from: 'decision', to: 'end_no',  label: 'No'  },\n  ],\n  theme: 'light',\n  palette: 'default',\n  direction: 'TB',\n});\n\n// ── Markdown string (compact, AI-friendly) ──────────────────────────────────\nconst svg2 = fig(`\n  figure flow\n  direction: LR\n  palette: default\n  title: Auth Flow\n  start((Start)) --> login[Enter Credentials]\n  login --> validate{Valid?}\n  validate --> dashboard((Dashboard)): yes\n  validate --> error[Show Error]: no\n  error --> login\n`);\n\n// Browser: inject into the DOM\ndocument.body.innerHTML = svg;\n\n// Node.js: write to file\nimport { writeFileSync } from 'fs';\nwriteFileSync('diagram.svg', svg);\n```\n\n## API Reference\n\n### `fig(input): string`\n\nThe single entry point. Returns a fully self-contained SVG string.\n\n**`input`** is either:\n\n- A **JSON config object** — typed `FigOptions` with the required `figure` field\n- A **markdown string** — Mermaid-like syntax, streaming-safe (never throws; partial input returns a valid empty SVG)\n\n```typescript\nimport { fig } from 'ai-figure';\n\n// JSON config\nfig({ figure: 'flow',     ...flowOptions     }); // flowchart\nfig({ figure: 'tree',     ...treeOptions     }); // tree / hierarchy\nfig({ figure: 'mindmap',  ...mindmapOptions  }); // root-centered mindmap\nfig({ figure: 'arch',     ...archOptions     }); // architecture diagram\nfig({ figure: 'sequence', ...sequenceOptions }); // sequence diagram\nfig({ figure: 'quadrant', ...quadrantOptions }); // quadrant chart\nfig({ figure: 'gantt',    ...ganttOptions    }); // Gantt chart\nfig({ figure: 'state',    ...stateOptions    }); // state machine\nfig({ figure: 'er',       ...erOptions       }); // ER data model\nfig({ figure: 'timeline', ...timelineOptions }); // timeline\nfig({ figure: 'swimlane', ...swimlaneOptions }); // swimlane flow\nfig({ figure: 'bubble',   ...bubbleOptions   }); // bubble chart\nfig({ figure: 'radar',    ...radarOptions    }); // radar / spider chart\n\n// markdown string\nfig(`figure flow\\na[A] --> b[B]`);\n```\n\n### `figure: 'flow'` — Flowchart\n\n![Flow](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/flow.svg)\n\n| Field       | Type            | Default        | Description                              |\n|-------------|-----------------|----------------|------------------------------------------|\n| `figure`    | `'flow'`        | **required**   | Selects the flowchart renderer           |\n| `nodes`     | `FlowNode[]`    | **required**   | List of nodes                            |\n| `edges`     | `FlowEdge[]`    | **required**   | List of directed edges                   |\n| `groups`    | `FlowGroup[]`   | `[]`           | Optional logical groups                  |\n| `title`     | `string`        | `undefined`    | Optional centered title above the diagram |\n| `subtitle`  | `string`        | `undefined`    | Optional centered subtitle below the title |\n| `theme`     | `ThemeType`     | `'light'`    | Light or dark rendering mode (`'light'` \\| `'dark'`) |\n| `palette`   | `PaletteType`   | `'default'`    | Color palette — see [Palette API](#palette-api) below |\n| `direction` | `Direction`     | `'TB'`         | Layout direction (`'TB'` or `'LR'`)      |\n\n#### `FlowNode`\n\n| Field   | Type       | Default      | Description                |\n|---------|------------|--------------|----------------------------|\n| `id`    | `string`   | **required** | Unique node identifier     |\n| `label` | `string`   | **required** | Text displayed in the node |\n| `type`  | `NodeType` | `'process'`  | Visual shape               |\n\n**Node types (`NodeType`)**\n\n| Value      | Shape               | Use case                  |\n|------------|---------------------|---------------------------|\n| `process`  | Rectangle           | Default step / action     |\n| `decision` | Diamond             | Conditional / branch      |\n| `terminal` | Rounded rectangle   | Start / End               |\n| `io`       | Parallelogram       | Input / Output            |\n\n#### `FlowEdge`\n\n| Field   | Type     | Default      | Description         |\n|---------|----------|--------------|---------------------|\n| `from`  | `string` | **required** | Source node ID      |\n| `to`    | `string` | **required** | Target node ID      |\n| `label` | `string` | `undefined`  | Optional edge label |\n\n#### `FlowGroup`\n\n| Field   | Type       | Default      | Description                        |\n|---------|------------|--------------|------------------------------------|\n| `id`    | `string`   | **required** | Unique group identifier            |\n| `label` | `string`   | **required** | Label shown above the group border |\n| `nodes` | `string[]` | **required** | IDs of nodes inside this group     |\n\n### `figure: 'tree'` — Tree Diagram\n\nRenders a hierarchy from a flat node list with `parent` references. Uses Dagre for layout.\n\n![Tree](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/tree.svg)\n\n| Field       | Type          | Default        | Description                        |\n|-------------|---------------|----------------|------------------------------------|\n| `figure`    | `'tree'`      | **required**   | Selects the tree renderer          |\n| `nodes`     | `TreeNode[]`  | **required**   | Flat list with optional parent ref |\n| `title`     | `string`      | `undefined`    | Optional centered title above the diagram |\n| `subtitle`  | `string`      | `undefined`    | Optional centered subtitle below the title |\n| `theme`     | `ThemeType`   | `'light'`    | Light or dark rendering mode (`'light'` \\| `'dark'`) |\n| `palette`   | `PaletteType` | `'default'`    | Color palette — see [Palette API](#palette-api) below |\n| `direction` | `Direction`   | `'TB'`         | Layout direction                   |\n\n```typescript\nfig({\n  figure: 'tree',\n  nodes: [\n    { id: 'ceo', label: 'CEO' },\n    { id: 'cto', label: 'CTO', parent: 'ceo' },\n    { id: 'coo', label: 'COO', parent: 'ceo' },\n  ],\n  theme: 'light',\n  palette: 'default',\n});\n```\n\n### `figure: 'mindmap'` — Mindmap Diagram\n\nRenders a root-centered mindmap. First-level branches are auto-balanced across left/right unless explicit `side` is provided.\n\n![Mindmap](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/mindmap.svg)\n\n| Field      | Type               | Default      | Description |\n|------------|--------------------|--------------|-------------|\n| `figure`   | `'mindmap'`        | **required** | Selects the mindmap renderer |\n| `nodes`    | `MindmapNode[]`    | **required** | Flat list with optional `parent` and `side` |\n| `title`    | `string`           | `undefined`  | Optional centered title above the diagram |\n| `subtitle` | `string`           | `undefined`  | Optional centered subtitle below the title |\n| `theme`    | `ThemeType`        | `'light'`    | Light or dark rendering mode (`'light'` \\| `'dark'`) |\n| `palette`  | `PaletteType`      | `'default'`  | Color palette — see [Palette API](#palette-api) below |\n\n#### `MindmapNode`\n\n| Field    | Type                  | Default      | Description |\n|----------|-----------------------|--------------|-------------|\n| `id`     | `string`              | **required** | Unique node identifier |\n| `label`  | `string`              | **required** | Text displayed in the node |\n| `parent` | `string`              | `undefined`  | Parent node id (omit for root) |\n| `side`   | `'left' \\| 'right'`   | auto         | Optional preferred branch side (best for root-level children) |\n\n```typescript\nfig({\n  figure: 'mindmap',\n  title: 'Product Strategy',\n  nodes: [\n    { id: 'root', label: 'Product Strategy' },\n    { id: 'market', label: 'Market', parent: 'root', side: 'left' },\n    { id: 'tech', label: 'Technology', parent: 'root', side: 'right' },\n    { id: 'smb', label: 'SMB', parent: 'market' },\n    { id: 'ai', label: 'AI Features', parent: 'tech' },\n  ],\n});\n```\n\n### `figure: 'arch'` — Architecture Diagram\n\nRenders a tech-stack landscape as layered, color-coded cards — no edges needed.\n\n![Architecture](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/arch.svg)\n\n| Field       | Type          | Default        | Description                              |\n|-------------|---------------|----------------|------------------------------------------|\n| `figure`    | `'arch'`      | **required**   | Selects the architecture renderer        |\n| `layers`    | `ArchLayer[]` | **required**   | Layers from top to bottom (TB) or left to right (LR) |\n| `title`     | `string`      | `undefined`    | Optional centered title above the diagram |\n| `subtitle`  | `string`      | `undefined`    | Optional centered subtitle below the title |\n| `theme`     | `ThemeType`   | `'light'`    | Light or dark rendering mode (`'light'` \\| `'dark'`) |\n| `palette`   | `PaletteType` | `'default'`    | Color palette — see [Palette API](#palette-api) below |\n| `direction` | `Direction`   | `'TB'`         | `'TB'` = layers stacked, `'LR'` = layers side-by-side |\n\n```typescript\nfig({\n  figure: 'arch',\n  layers: [\n    { id: 'fe', label: 'Frontend', nodes: [{ id: 'react', label: 'React' }, { id: 'vue', label: 'Vue' }] },\n    { id: 'be', label: 'Backend',  nodes: [{ id: 'node', label: 'Node.js' }] },\n  ],\n});\n```\n\n### `figure: 'sequence'` — Sequence Diagram\n\nRenders a sequence diagram with vertical lifelines and horizontal message arrows.\n\n![Sequence](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/sequence.svg)\n\n| Field      | Type           | Default        | Description                           |\n|------------|----------------|----------------|---------------------------------------|\n| `figure`   | `'sequence'`   | **required**   | Selects the sequence renderer         |\n| `actors`   | `string[]`     | **required**   | Ordered list of participant names     |\n| `messages` | `SeqMessage[]` | **required**   | Ordered list of message arrows        |\n| `title`    | `string`       | `undefined`    | Optional centered title above the diagram |\n| `subtitle` | `string`       | `undefined`    | Optional centered subtitle below the title |\n| `theme`    | `ThemeType`    | `'light'`    | Light or dark rendering mode (`'light'` \\| `'dark'`) |\n| `palette`  | `PaletteType`  | `'default'`    | Color palette — see [Palette API](#palette-api) below |\n\n```typescript\nfig({\n  figure: 'sequence',\n  actors: ['Browser', 'API', 'DB'],\n  messages: [\n    { from: 'Browser', to: 'API', label: 'POST /login' },\n    { from: 'API',     to: 'DB',  label: 'SELECT user' },\n    { from: 'DB',      to: 'API', label: 'user row',  style: 'return' },\n    { from: 'API',     to: 'Browser', label: '200 OK', style: 'return' },\n  ],\n});\n```\n\n### `figure: 'quadrant'` — Quadrant Chart\n\nRenders a 2D quadrant scatter plot. Points are placed by normalized `x`/`y` values (0–1) and auto-colored by which quadrant they fall in.\n\n![Quadrant](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/quadrant.svg)\n\n| Field       | Type               | Default        | Description                                         |\n|-------------|--------------------|----------------|-----------------------------------------------------|\n| `figure`    | `'quadrant'`       | **required**   | Selects the quadrant renderer                       |\n| `xAxis`     | `AxisConfig`       | **required**   | X-axis label, min and max tick labels               |\n| `yAxis`     | `AxisConfig`       | **required**   | Y-axis label, min and max tick labels               |\n| `quadrants` | `[TL, TR, BL, BR]` | **required**   | Corner labels: top-left, top-right, bottom-left, bottom-right |\n| `points`    | `QuadrantPoint[]`  | **required**   | Data points to plot                                 |\n| `title`     | `string`           | `undefined`    | Optional centered title above the diagram           |\n| `subtitle`  | `string`           | `undefined`    | Optional centered subtitle below the title          |\n| `theme`     | `ThemeType`        | `'light'`    | Light or dark rendering mode (`'light'` \\| `'dark'`) |\n| `palette`   | `PaletteType`      | `'default'`    | Color palette — see [Palette API](#palette-api) below |\n\n#### `AxisConfig`\n\n| Field   | Type     | Description              |\n|---------|----------|--------------------------|\n| `label` | `string` | Axis title               |\n| `min`   | `string` | Label at the low end     |\n| `max`   | `string` | Label at the high end    |\n\n#### `QuadrantPoint`\n\n| Field   | Type     | Description                             |\n|---------|----------|-----------------------------------------|\n| `id`    | `string` | Unique identifier                       |\n| `label` | `string` | Text shown next to the point            |\n| `x`     | `number` | Normalized X position (0 = left, 1 = right) |\n| `y`     | `number` | Normalized Y position (0 = bottom, 1 = top) |\n\n```typescript\nfig({\n  figure: 'quadrant',\n  xAxis: { label: 'Effort', min: 'Low', max: 'High' },\n  yAxis: { label: 'Value',  min: 'Low', max: 'High' },\n  quadrants: ['Quick Wins', 'Major Projects', 'Fill-ins', 'Thankless Tasks'],\n  points: [\n    { id: 'a', label: 'Feature A', x: 0.2,  y: 0.85 },\n    { id: 'b', label: 'Feature B', x: 0.75, y: 0.80 },\n    { id: 'c', label: 'Feature C', x: 0.5,  y: 0.6  },\n    { id: 'd', label: 'Feature D', x: 0.3,  y: 0.2  },\n    { id: 'e', label: 'Feature E', x: 0.8,  y: 0.25 },\n  ],\n  theme: 'light',\n  palette: 'default',\n});\n```\n\n### `figure: 'gantt'` — Gantt Chart\n\nRenders a project timeline with task bars, optional group headers, and milestone markers. Canvas width is fixed at 804 px; height auto-adapts to the number of rows. The time axis ticks adjust automatically to the date range (weekly / monthly / quarterly).\n\n![Gantt](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/gantt.svg)\n\n| Field        | Type               | Default      | Description                                  |\n|--------------|--------------------|--------------|----------------------------------------------|\n| `figure`     | `'gantt'`          | **required** | Selects the Gantt renderer                   |\n| `tasks`      | `GanttTask[]`      | **required** | List of task bars                            |\n| `milestones` | `GanttMilestone[]` | `[]`         | Optional milestone markers                   |\n| `title`      | `string`           | `undefined`  | Optional centered title above the diagram    |\n| `subtitle`   | `string`           | `undefined`  | Optional centered subtitle below the title   |\n| `theme`      | `ThemeType`        | `'light'`    | Light or dark rendering mode                 |\n| `palette`    | `PaletteType`      | `'default'`  | Color palette — see [Palette API](#palette-api) below |\n\n#### `GanttTask`\n\n| Field     | Type     | Default      | Description                                                        |\n|-----------|----------|--------------|--------------------------------------------------------------------|\n| `id`      | `string` | **required** | Unique task identifier                                             |\n| `label`   | `string` | **required** | Task name shown in the label column and inside the bar            |\n| `start`   | `string` | **required** | Start date `yyyy-mm-dd`                                           |\n| `end`     | `string` | **required** | End date `yyyy-mm-dd`                                             |\n| `groupId` | `string` | `undefined`  | Tasks sharing the same `groupId` are clustered under a group header |\n| `color`   | `string` | `undefined`  | Optional custom bar color (6-digit hex, e.g. `'#e64980'`)         |\n\n#### `GanttMilestone`\n\n| Field   | Type     | Default      | Description                       |\n|---------|----------|--------------|-----------------------------------|\n| `date`  | `string` | **required** | Milestone date `yyyy-mm-dd`       |\n| `label` | `string` | **required** | Short label near the diamond icon |\n\n```typescript\nfig({\n  figure: 'gantt',\n  title: 'Project Roadmap',\n  tasks: [\n    { id: 'design', label: 'Design',       start: '2025-01-06', end: '2025-01-24' },\n    { id: 'fe',     label: 'Frontend Dev', start: '2025-01-20', end: '2025-02-28', groupId: 'dev' },\n    { id: 'be',     label: 'Backend Dev',  start: '2025-01-13', end: '2025-03-07', groupId: 'dev' },\n    { id: 'qa',     label: 'QA Testing',   start: '2025-02-24', end: '2025-03-14', groupId: 'qa'  },\n    { id: 'deploy', label: 'Deploy',       start: '2025-03-17', end: '2025-03-21' },\n  ],\n  milestones: [\n    { date: '2025-01-24', label: 'Design freeze' },\n    { date: '2025-03-21', label: 'Launch' },\n  ],\n  theme: 'light',\n  palette: 'default',\n});\n```\n\n### `figure: 'state'` — State Machine\n\nRenders a UML state machine with dagre layout. Supports start (●) and end (◎) pseudo-states, accent states, self-loops, and labeled transitions.\n\n![State Machine](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/state.svg)\n\n| Field         | Type                  | Default      | Description                                  |\n|---------------|-----------------------|--------------|----------------------------------------------|\n| `figure`      | `'state'`             | **required** | Selects the state machine renderer           |\n| `nodes`       | `StateNode[]`         | **required** | List of states                               |\n| `transitions` | `StateTransition[]`   | **required** | List of directed transitions                 |\n| `title`       | `string`              | `undefined`  | Optional centered title above the diagram    |\n| `subtitle`    | `string`              | `undefined`  | Optional centered subtitle below the title   |\n| `theme`       | `ThemeType`           | `'light'`    | Light or dark rendering mode                 |\n| `palette`     | `PaletteType`         | `'default'`  | Color palette — see [Palette API](#palette-api) below |\n\n#### `StateNode`\n\n| Field    | Type             | Default     | Description                                           |\n|----------|------------------|-------------|-------------------------------------------------------|\n| `id`     | `string`         | **required**| Unique state identifier                               |\n| `label`  | `string`         | **required**| Text displayed in the state box                       |\n| `type`   | `StateNodeType`  | `'state'`   | `'state'` \\| `'start'` \\| `'end'`                   |\n| `accent` | `boolean`        | `false`     | Highlight this state with the accent color (max 1–2)  |\n\n#### `StateTransition`\n\n| Field   | Type     | Default      | Description                                           |\n|---------|----------|--------------|-------------------------------------------------------|\n| `from`  | `string` | **required** | Source state ID                                       |\n| `to`    | `string` | **required** | Target state ID                                       |\n| `label` | `string` | `undefined`  | Optional label — typically `event [guard] / action`   |\n\n```typescript\nfig({\n  figure: 'state',\n  title: 'Order Status',\n  nodes: [\n    { id: 'start',      label: '',           type: 'start' },\n    { id: 'idle',       label: 'Idle' },\n    { id: 'processing', label: 'Processing' },\n    { id: 'shipped',    label: 'Shipped' },\n    { id: 'failed',     label: 'Failed',     accent: true },\n    { id: 'end',        label: '',           type: 'end' },\n  ],\n  transitions: [\n    { from: 'start',      to: 'idle' },\n    { from: 'idle',       to: 'processing', label: 'place order' },\n    { from: 'processing', to: 'shipped',    label: 'confirmed' },\n    { from: 'processing', to: 'failed',     label: 'error' },\n    { from: 'failed',     to: 'idle',       label: 'retry' },\n    { from: 'shipped',    to: 'end' },\n  ],\n});\n```\n\n### `figure: 'er'` — Entity-Relationship Diagram\n\nRenders a database schema with entity boxes (header + field list) and relationship lines with optional cardinality annotations.\n\n![ER Diagram](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/er.svg)\n\n| Field      | Type           | Default      | Description                                  |\n|------------|----------------|--------------|----------------------------------------------|\n| `figure`   | `'er'`         | **required** | Selects the ER renderer                      |\n| `entities` | `ErEntity[]`   | **required** | List of entities (tables)                    |\n| `relations`| `ErRelation[]` | **required** | List of relationship lines                   |\n| `title`    | `string`       | `undefined`  | Optional centered title above the diagram    |\n| `subtitle` | `string`       | `undefined`  | Optional centered subtitle below the title   |\n| `theme`    | `ThemeType`    | `'light'`    | Light or dark rendering mode                 |\n| `palette`  | `PaletteType`  | `'default'`  | Color palette — see [Palette API](#palette-api) below |\n\n#### `ErEntity`\n\n| Field    | Type        | Default      | Description                                                  |\n|----------|-------------|--------------|--------------------------------------------------------------|\n| `id`     | `string`    | **required** | Unique entity identifier                                     |\n| `label`  | `string`    | **required** | Entity display name shown in the header                      |\n| `fields` | `ErField[]` | **required** | Ordered list of fields (columns)                             |\n| `accent` | `boolean`   | `false`      | Highlight as the aggregate root (max 1)                      |\n\n#### `ErField`\n\n| Field  | Type          | Default      | Description                                     |\n|--------|---------------|--------------|-------------------------------------------------|\n| `name` | `string`      | **required** | Field name                                      |\n| `type` | `string`      | `undefined`  | Data type string (e.g. `'uuid'`, `'text'`)      |\n| `key`  | `'pk'\\|'fk'`  | `undefined`  | `'pk'` = primary key (#), `'fk'` = foreign key (→) |\n\n#### `ErRelation`\n\n| Field      | Type     | Default      | Description                                        |\n|------------|----------|--------------|----------------------------------------------------|\n| `from`     | `string` | **required** | Source entity ID                                   |\n| `to`       | `string` | **required** | Target entity ID                                   |\n| `label`    | `string` | `undefined`  | Optional label centered on the line                |\n| `fromCard` | `string` | `undefined`  | Cardinality at the `from` end (e.g. `'1'`, `'N'`) |\n| `toCard`   | `string` | `undefined`  | Cardinality at the `to` end                        |\n\n```typescript\nfig({\n  figure: 'er',\n  title: 'Blog Schema',\n  entities: [\n    { id: 'user', label: 'User',\n      fields: [{ name: 'id', type: 'uuid', key: 'pk' }, { name: 'email', type: 'text' }] },\n    { id: 'post', label: 'Post',\n      fields: [{ name: 'id', type: 'uuid', key: 'pk' }, { name: 'author_id', type: 'uuid', key: 'fk' }] },\n  ],\n  relations: [\n    { from: 'user', to: 'post', label: 'writes', fromCard: '1', toCard: 'N' },\n  ],\n});\n```\n\n### `figure: 'timeline'` — Timeline\n\nRenders a horizontal date axis with events spaced proportionally. Labels alternate above and below the axis to reduce collision. Major milestones are rendered with a larger accent dot.\n\n![Timeline](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/timeline.svg)\n\n| Field      | Type              | Default      | Description                                  |\n|------------|-------------------|--------------|----------------------------------------------|\n| `figure`   | `'timeline'`      | **required** | Selects the timeline renderer                |\n| `events`   | `TimelineEvent[]` | **required** | List of events (auto-sorted by date)         |\n| `title`    | `string`          | `undefined`  | Optional centered title above the diagram    |\n| `subtitle` | `string`          | `undefined`  | Optional centered subtitle below the title   |\n| `theme`    | `ThemeType`       | `'light'`    | Light or dark rendering mode                 |\n| `palette`  | `PaletteType`     | `'default'`  | Color palette — see [Palette API](#palette-api) below |\n\n#### `TimelineEvent`\n\n| Field       | Type      | Default      | Description                                          |\n|-------------|-----------|--------------|------------------------------------------------------|\n| `id`        | `string`  | **required** | Unique event identifier                              |\n| `label`     | `string`  | **required** | Short label displayed near the event dot             |\n| `date`      | `string`  | **required** | Event date in `yyyy-mm-dd` format                    |\n| `milestone` | `boolean` | `false`      | Render as a major milestone (larger accent-color dot)|\n\n```typescript\nfig({\n  figure: 'timeline',\n  title: 'Product History',\n  events: [\n    { id: 'v1',   label: 'v1.0 Launch',   date: '2020-01-15', milestone: true },\n    { id: 'v15',  label: 'v1.5 Patch',    date: '2021-06-01' },\n    { id: 'v2',   label: 'v2.0 Redesign', date: '2022-03-10', milestone: true },\n    { id: 'v3',   label: 'v3.0 AI',       date: '2023-11-01', milestone: true },\n  ],\n});\n```\n\n### `figure: 'swimlane'` — Swimlane Flow\n\nRenders a cross-functional flowchart with horizontal lane bands. Nodes are placed in their declared lane; cross-lane edges use S-curve routing.\n\n![Swimlane](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/swimlane.svg)\n\n| Field      | Type              | Default      | Description                                  |\n|------------|-------------------|--------------|----------------------------------------------|\n| `figure`   | `'swimlane'`      | **required** | Selects the swimlane renderer                |\n| `lanes`    | `string[]`        | **required** | Lane labels in display order                 |\n| `nodes`    | `SwimlaneNode[]`  | **required** | Nodes placed inside their respective lanes   |\n| `edges`    | `SwimlaneEdge[]`  | **required** | Directed edges between nodes                 |\n| `title`    | `string`          | `undefined`  | Optional centered title above the diagram    |\n| `subtitle` | `string`          | `undefined`  | Optional centered subtitle below the title   |\n| `theme`    | `ThemeType`       | `'light'`    | Light or dark rendering mode                 |\n| `palette`  | `PaletteType`     | `'default'`  | Color palette — see [Palette API](#palette-api) below |\n\n#### `SwimlaneNode`\n\n| Field   | Type       | Default      | Description                              |\n|---------|------------|--------------|------------------------------------------|\n| `id`    | `string`   | **required** | Unique node identifier                   |\n| `label` | `string`   | **required** | Text displayed in the node               |\n| `lane`  | `string`   | **required** | Lane label this node belongs to          |\n| `type`  | `NodeType` | `'process'`  | Visual shape (same as flowchart nodes)   |\n\n#### `SwimlaneEdge`\n\n| Field   | Type     | Default      | Description         |\n|---------|----------|--------------|---------------------|\n| `from`  | `string` | **required** | Source node ID      |\n| `to`    | `string` | **required** | Target node ID      |\n| `label` | `string` | `undefined`  | Optional edge label |\n\n```typescript\nfig({\n  figure: 'swimlane',\n  title: 'Order Processing',\n  lanes: ['Customer', 'Warehouse', 'Shipping'],\n  nodes: [\n    { id: 'order',   label: 'Place Order',     lane: 'Customer'  },\n    { id: 'pay',     label: 'Confirm Payment', lane: 'Customer'  },\n    { id: 'receive', label: 'Receive Order',   lane: 'Warehouse' },\n    { id: 'pack',    label: 'Pack Items',      lane: 'Warehouse' },\n    { id: 'ship',    label: 'Ship Package',    lane: 'Shipping'  },\n  ],\n  edges: [\n    { from: 'order',   to: 'pay'     },\n    { from: 'pay',     to: 'receive' },\n    { from: 'receive', to: 'pack'    },\n    { from: 'pack',    to: 'ship'    },\n  ],\n});\n```\n\n### `figure: 'bubble'` — Bubble Chart\n\nRenders a packed-bubble chart where each item's area is proportional to its value. Positions are computed automatically by a greedy circle-packing algorithm — no coordinates needed. Bubbles pulse with a subtle SMIL animation for a lively visual effect.\n\n![Bubble](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/bubble.svg)\n\n| Field      | Type            | Default      | Description                                   |\n|------------|-----------------|--------------|-----------------------------------------------|\n| `figure`   | `'bubble'`      | **required** | Selects the bubble chart renderer             |\n| `items`    | `BubbleItem[]`  | **required** | Bubble data items                             |\n| `title`    | `string`        | `undefined`  | Optional centered title above the diagram    |\n| `subtitle` | `string`        | `undefined`  | Optional centered subtitle below the title   |\n| `theme`    | `ThemeType`     | `'light'`    | Light or dark rendering mode                  |\n| `palette`  | `PaletteType`   | `'default'`  | Color palette — see [Palette API](#palette-api) below |\n\n#### `BubbleItem`\n\n| Field   | Type     | Default      | Description                                            |\n|---------|----------|--------------|--------------------------------------------------------|\n| `id`    | `string` | `undefined`  | Optional unique identifier                             |\n| `label` | `string` | **required** | Text label displayed inside or below the bubble        |\n| `value` | `number` | **required** | Positive number — bubble area is proportional to value |\n\n```typescript\nfig({\n  figure: 'bubble',\n  title: 'Market Analysis',\n  items: [\n    { label: 'Product A', value: 75 },\n    { label: 'Product B', value: 50 },\n    { label: 'Product C', value: 85 },\n  ],\n  palette: 'default',\n});\n```\n\n### `figure: 'radar'` — Radar / Spider Chart\n\nRenders a radar (spider / web) chart with multiple overlaid polygon series. Each axis is a spoke radiating from the centre; values 0–100 map to 0–100% of the axis radius. Multiple series are overlaid with translucent fills so they remain readable when they overlap. A legend below the chart labels each series.\n\n![Radar](https://raw.githubusercontent.com/hustcc/ai-figure/main/assets/radar.svg)\n\n| Field      | Type            | Default      | Description                                   |\n|------------|-----------------|--------------|-----------------------------------------------|\n| `figure`   | `'radar'`       | **required** | Selects the radar chart renderer              |\n| `axes`     | `string[]`      | **required** | Ordered list of axis labels (3 or more recommended) |\n| `series`   | `RadarSeries[]` | **required** | One or more data series to overlay            |\n| `title`    | `string`        | `undefined`  | Optional centered title above the diagram    |\n| `subtitle` | `string`        | `undefined`  | Optional centered subtitle below the title   |\n| `theme`    | `ThemeType`     | `'light'`    | Light or dark rendering mode                  |\n| `palette`  | `PaletteType`   | `'default'`  | Color palette — see [Palette API](#palette-api) below |\n\n#### `RadarSeries`\n\n| Field    | Type       | Default      | Description                                                   |\n|----------|------------|--------------|---------------------------------------------------------------|\n| `label`  | `string`   | **required** | Series name shown in the legend                               |\n| `values` | `number[]` | **required** | One value per axis in the same order as `axes` (range 0–100) |\n\n```typescript\nfig({\n  figure: 'radar',\n  title: 'Framework Comparison',\n  axes: ['Performance', 'Scalability', 'DX', 'Ecosystem', 'Tooling'],\n  series: [\n    { label: 'React',   values: [75, 80, 90, 95, 88] },\n    { label: 'Vue',     values: [82, 72, 90, 82, 80] },\n    { label: 'Angular', values: [65, 92, 72, 90, 86] },\n  ],\n  palette: 'antv',\n});\n```\n\n### Palette API\n\nAll thirteen diagram types accept two independent styling parameters:\n\n| Field     | Type                   | Default       | Description                          |\n|-----------|------------------------|---------------|--------------------------------------|\n| `theme`   | `'light' \\| 'dark'`   | `'light'`     | Background and text rendering mode   |\n| `palette` | `string \\| string[]`  | `'default'`   | Color palette for nodes              |\n\n**`palette` values:**\n\n| Value | Description |\n|-------|-------------|\n| `'default'` | Built-in multi-hue palette — `process`=blue, `decision`=amber, `terminal`=green, `io`=purple |\n| `'antv'` | AntV G2 categorical palette — cornflower-blue, coral-orange, mint-teal, violet |\n| `'drawio'` | draw.io / diagrams.net shape palette — sky-blue, amber, sage, red |\n| `'figma'` | Figma / design-tool palette — indigo, cyan, emerald, rose-pink |\n| `'vega'` | Vega / Vega-Lite categorical palette — steel-blue, orange, teal, crimson |\n| `'mono-blue'` | Monochrome blue — all four node types use blue-family shades |\n| `'mono-green'` | Monochrome green — all four node types use green-family shades |\n| `'mono-purple'` | Monochrome purple — all four node types use purple-family shades |\n| `'mono-orange'` | Monochrome orange — all four node types use orange-family shades |\n| `string[]` | 4-element hex array mapped to `[process, decision, terminal, io]` |\n\n```typescript\n// Built-in palette, dark mode\nfig({ figure: 'flow', nodes, edges, theme: 'dark', palette: 'default' });\n\n// AntV G2 palette\nfig({ figure: 'flow', nodes, edges, palette: 'antv' });\n\n// draw.io palette with dark background\nfig({ figure: 'flow', nodes, edges, theme: 'dark', palette: 'drawio' });\n\n// Monochrome blue\nfig({ figure: 'flow', nodes, edges, palette: 'mono-blue' });\n\n// Custom hex palette\nfig({ figure: 'flow', nodes, edges, palette: ['#e64980', '#ae3ec9', '#7048e8', '#1098ad'] });\n```\n\n### Markdown syntax\n\n`fig()` also accepts a plain **markdown string** as input. The first non-empty line must be `figure <type>`. Config, data, and comment lines follow.\n\n| Line type | Syntax | Example |\n|-----------|--------|---------|\n| Header | `figure <type>` | `figure flow` |\n| Config | `key: value` | `direction: LR` · `palette: antv` · `title: My Chart` |\n| Comment | `%% text` | `%% ignored` |\n| Data | diagram-specific | see per-diagram syntax below |\n\nConfig keys available in all diagram types: `title`, `subtitle`, `theme` (`light`\\|`dark`), `palette`, `direction` (`TB`\\|`LR`).\n\n#### Node notation (flow / tree / mindmap / arch)\n\n| Notation | Shape |\n|----------|-------|\n| `id[label]` | process (rectangle) |\n| `id{label}` | decision (diamond) |\n| `id((label))` | terminal (pill) |\n| `id[/label/]` | io (parallelogram) |\n| `id` | process (bare id used as label) |\n\n#### Per-diagram syntax\n\n<details>\n<summary><strong>flow</strong></summary>\n\n```\nfigure flow\ndirection: LR\ntitle: Optional Title\nsubtitle: Optional Subtitle\nid[Label]                          %% standalone node definition\nA[Source] --> B[Target]            %% edge\nA --> B[Target]: label             %% labeled edge\ngroup GroupName: id1, id2, id3     %% logical group\n```\n</details>\n\n<details>\n<summary><strong>tree</strong></summary>\n\n```\nfigure tree\ndirection: LR\ntitle: Optional Title\nroot[Root]                   %% root node (no parent)\nroot --> child[Child]        %% parent → child relationship\n```\n</details>\n\n<details>\n<summary><strong>arch</strong></summary>\n\n```\nfigure arch\ndirection: TB\ntitle: Optional Title\nlayer Layer Label            %% layer declaration (label serves as id)\n  nodeId[Node Label]         %% node in current layer (indentation optional)\n```\n</details>\n\n<details>\n<summary><strong>mindmap</strong></summary>\n\n```\nfigure mindmap\ntitle: Optional Title\nsubtitle: Optional Subtitle\nroot[Root Topic]\nroot --> leftBranch[Left Branch]\nroot --> rightBranch[Right Branch]\nleftBranch --> leaf[Leaf]\n```\n</details>\n\n<details>\n<summary><strong>sequence</strong></summary>\n\n```\nfigure sequence\ntitle: Optional Title\nactors: Actor1, Actor2, Actor3     %% optional; inferred from messages if omitted\nActor1 -> Actor2: message          %% solid arrow\nActor2 --> Actor1: response        %% dashed return arrow\nActor1 -> Actor2                   %% arrow without label\n```\n</details>\n\n<details>\n<summary><strong>quadrant</strong></summary>\n\n```\nfigure quadrant\ntitle: Optional Title\nx-axis: min .. max                 %% axis range (label defaults to \"\")\nx-axis Label: min .. max           %% axis range with explicit axis label\ny-axis: min .. max\nquadrant-1: Top-Left Name          %% 1=TL, 2=TR, 3=BL, 4=BR\nquadrant-2: Top-Right Name\nquadrant-3: Bottom-Left Name\nquadrant-4: Bottom-Right Name\nPoint Label: 0.3, 0.7             %% data point (x, y in [0, 1])\n```\n</details>\n\n<details>\n<summary><strong>gantt</strong></summary>\n\n```\nfigure gantt\ntitle: Optional Title\nsection Section Name               %% group header (applied to subsequent tasks)\n  Task Label: id, start, end       %% task bar (dates: yyyy-mm-dd)\nmilestone: Label, date             %% milestone diamond\n```\n</details>\n\n<details>\n<summary><strong>state</strong></summary>\n\n```\nfigure state\ntitle: Optional Title\nidle[Idle]                         %% normal state (rounded rectangle)\naccent: failed                     %% highlight as focal/error state\nstart --> idle                     %% start pseudo-state → first state\nidle --> processing: order placed  %% transition with optional label\nprocessing --> end: shipped        %% end pseudo-state\n```\n</details>\n\n<details>\n<summary><strong>er</strong></summary>\n\n```\nfigure er\ntitle: Optional Title\nentity User                        %% entity declaration (name = id = label)\n  id pk: uuid                      %% field: name [pk|fk]: type\n  email: text\n  name                             %% bare field (no type)\nentity Post\n  id pk: uuid\n  author_id fk: uuid\nUser --> Post: writes              %% relationship line\naccent: User                       %% mark as aggregate root\n```\n</details>\n\n<details>\n<summary><strong>timeline</strong></summary>\n\n```\nfigure timeline\ntitle: Optional Title\n2020-01-15: v1.0 Launch milestone  %% major milestone (larger accent dot)\n2021-06-01: v1.5 Patch\n2022-03-10: v2.0 Redesign milestone\n```\n</details>\n\n<details>\n<summary><strong>swimlane</strong></summary>\n\n```\nfigure swimlane\ntitle: Optional Title\nsection Customer                          %% declare lane (subsequent nodes belong here)\n  order[Place Order]                      %% node in current lane\n  pay[Confirm Payment]\nsection Warehouse\n  pack[Pack Items]\nsection Shipping\n  ship[Ship Package]\norder --> pack                            %% edges between nodes\npack --> ship\n```\n</details>\n\n<details>\n<summary><strong>bubble</strong></summary>\n\n```\nfigure bubble\ntitle: Optional Title\n%% e.g. \"Product A: 75\"\nLabel: value\n```\n</details>\n\n<details>\n<summary><strong>radar</strong></summary>\n\n```\nfigure radar\ntitle: Optional Title\n%% axes: comma-separated axis labels\naxes: Axis1, Axis2, Axis3, ...\n%% one value (0-100) per axis\nSeries A: 80, 70, 90, ...\nSeries B: 60, 85, 75, ...\n```\n</details>\n\n## Using with AI\n\nThis library ships a **[`SKILL.md`](https://github.com/hustcc/ai-figure/blob/main/SKILL.md)** — a machine-readable skill file that AI agents (Copilot, Cursor, Claude, etc.) can load as context.\n\n```\n# Load the skill into your AI context:\n@SKILL.md\n```\n\n`fig()` accepts a plain markdown string, which makes it ideal for AI generation:\n- **Streaming-safe** — partial output never throws; the diagram fills in progressively as more tokens arrive\n- **Compact** — the markdown syntax is ~5× shorter than an equivalent JSON config\n\n**Prompt example:**\n> \"Draw a flowchart showing the user login process.\"\n\n**AI-generated code:**\n```typescript\nimport { fig } from 'ai-figure';\n\nconst svg = fig(`\n  figure flow\n  direction: TB\n  palette: default\n  title: User Login\n  start((Start)) --> creds[Enter Credentials]\n  creds --> validate{Valid?}\n  validate --> dashboard((Dashboard)): yes\n  validate --> error[Show Error]: no\n  error --> creds\n  dashboard --> done((End))\n`);\n```\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build (ESM + CJS)\nnpm run build\n\n# Run tests\nnpm test\n\n# Type check\nnpm run typecheck\n\n# Start browser demo (after building)\nnpx serve .\n# Then open: http://localhost:3000/index.html\n```\n\n## License\n\nMIT © [hustcc](https://github.com/hustcc)\n","readmeFilename":"README.md","homepage":"https://github.com/hustcc/ai-figure#readme","repository":{"type":"git","url":"git+ssh://git@github.com/hustcc/ai-figure.git"},"bugs":{"url":"https://github.com/hustcc/ai-figure/issues"}}