mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-09-02 01:20:23 +08:00
feat(diagram-engine): flex knobs (grow/align/pad) + inline rich-text labels
The expressiveness gap between engine output and hand-written XML came down to two missing capabilities, both generic: - Block layout inside a box: nested containers already existed, but there was no way to split space by weight, pin a child to an edge, or tighten padding. Added grow (flex-grow over the parent's leftover flow-axis space, TeX's glue), align (start/center/end/stretch on the cross axis) and pad (per-group interior padding). All three round-trip via dai_grow/dai_align/ dai_pad markers. - Inline rich text: labels already render HTML (html=1 on every style, esc() entities decode back), but the measure pass counted markup as text. The visibleText() strip makes autoBoxSize measure what draw.io draws: <br> is a line, other inline tags are invisible. Graphviz (HTML-like table labels), D2 (grid containers + markdown-in-shape) and TeX (box+glue) converged on exactly this design: nested boxes for block structure, proportional glue, a small inline set for text — never full HTML. Prompts teach the composition with a comparison-card recipe; verified by rebuilding the CoT poster end to end in the real editor.
This commit is contained in:
@@ -98,6 +98,18 @@ export const OperationSchema = z.discriminatedUnion("op", [
|
||||
.describe(
|
||||
"Flowchart outline: decision=diamond, terminator=start/end, data=input/output, document=report. Omit for a plain rectangle",
|
||||
),
|
||||
grow: z
|
||||
.number()
|
||||
.optional()
|
||||
.describe(
|
||||
"Flex-grow weight: this box takes that share of the parent's leftover space along its stacking axis. Omit for natural size",
|
||||
),
|
||||
align: z
|
||||
.enum(["start", "center", "end", "stretch"])
|
||||
.optional()
|
||||
.describe(
|
||||
"Cross-axis position in the parent: start/end pin to an edge, stretch fills the axis (a divider or highlight bar spanning its card). Default center",
|
||||
),
|
||||
lane: z
|
||||
.number()
|
||||
.optional()
|
||||
@@ -148,6 +160,24 @@ export const OperationSchema = z.discriminatedUnion("op", [
|
||||
"Group stencil name, e.g. 'group_vpc'; omit for a plain frame",
|
||||
),
|
||||
gap: z.number().optional(),
|
||||
pad: z
|
||||
.number()
|
||||
.optional()
|
||||
.describe(
|
||||
"Interior padding px (default 24). Small values make tight cards; nest containers for internal structure",
|
||||
),
|
||||
grow: z
|
||||
.number()
|
||||
.optional()
|
||||
.describe(
|
||||
"Flex-grow weight: this container takes that share of the parent's leftover space. E.g. two columns with grow 2 and 1 split the width 2:1",
|
||||
),
|
||||
align: z
|
||||
.enum(["start", "center", "end", "stretch"])
|
||||
.optional()
|
||||
.describe(
|
||||
"Cross-axis position in the parent: start/end pin to an edge, stretch fills. Default center",
|
||||
),
|
||||
after: z.string().optional(),
|
||||
}),
|
||||
z.object({
|
||||
@@ -414,6 +444,10 @@ export function applyOperations(
|
||||
...(op.stroke ? { stroke: op.stroke } : {}),
|
||||
...(op.role ? { role: op.role } : {}),
|
||||
...(op.group ? { group: op.group } : {}),
|
||||
...(op.grow && op.grow > 0 ? { grow: op.grow } : {}),
|
||||
...(op.align && op.align !== "center"
|
||||
? { align: op.align }
|
||||
: {}),
|
||||
...cellOf(op),
|
||||
}
|
||||
else if (op.op === "add_container")
|
||||
@@ -427,6 +461,11 @@ export function applyOperations(
|
||||
children: [],
|
||||
...(op.role ? { role: op.role } : {}),
|
||||
...(op.group ? { group: op.group } : {}),
|
||||
...(op.grow && op.grow > 0 ? { grow: op.grow } : {}),
|
||||
...(op.align && op.align !== "center"
|
||||
? { align: op.align }
|
||||
: {}),
|
||||
...(op.pad != null ? { pad: Math.max(0, op.pad) } : {}),
|
||||
}
|
||||
else if (op.op === "add_grid")
|
||||
node = {
|
||||
|
||||
Reference in New Issue
Block a user