@ufira/vibma 1.1.3-rc1 → 1.1.3-rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp.cjs CHANGED
@@ -412,7 +412,7 @@ Create frame-like containers
412
412
 
413
413
  Example: frames(method:"create", type:"auto_layout", layoutMode:"VERTICAL", itemSpacing:16, padding:24)
414
414
 
415
- Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line | group | boolean_operation | svg)
415
+ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line | group | boolean_operation | svg | slot)
416
416
 
417
417
  ## frame \u2014 General-purpose frame \u2014 shrinks to content by default, static when width+height given
418
418
  name (string, optional) \u2014 Node name
@@ -631,7 +631,64 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
631
631
  name (string, optional) \u2014 Layer name (default: 'SVG')
632
632
  parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
633
633
  x (number, optional) \u2014 X position (default: 0)
634
- y (number, optional) \u2014 Y position (default: 0)`,
634
+ y (number, optional) \u2014 Y position (default: 0)
635
+
636
+ ## slot \u2014 Create a slot inside a component. Slots are placeholder containers that instance users fill with content. Defaults to VERTICAL auto-layout with FILL/HUG sizing \u2014 ready to receive children. Accepts all frame layout properties.
637
+ name (string, optional) \u2014 Node name
638
+ parentId (string, optional) \u2014 Parent node ID inside the owning component. Required unless componentId is provided.
639
+ x (number, optional) \u2014 X position (default: 0)
640
+ y (number, optional) \u2014 Y position (default: 0)
641
+ width (number, optional) \u2014 Width in px (omit to shrink-to-content via HUG)
642
+ height (number, optional) \u2014 Height in px (omit to shrink-to-content via HUG)
643
+ rotation (number, optional) \u2014 Rotation in degrees (0-360)
644
+ visible (boolean, optional) \u2014 Show/hide (default true)
645
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
646
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
647
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
648
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
649
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
650
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
651
+ fillStyleName (string, optional) \u2014 Paint style name for fill
652
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
653
+ imageUrl (string, optional) \u2014 Image source \u2014 'pexel:<id>' for Pexels photos, a public URL, or a local file path. SVGs are inserted as vectors; raster images become IMAGE fills.
654
+ imageScaleMode (FILL | FIT | CROP | TILE, optional) \u2014 How the image is scaled within the frame (default: FILL)
655
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
656
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
657
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
658
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
659
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
660
+ strokeTopWeight (string, optional)
661
+ strokeBottomWeight (string, optional)
662
+ strokeLeftWeight (string, optional)
663
+ strokeRightWeight (string, optional)
664
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
665
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
666
+ topLeftRadius (string, optional)
667
+ topRightRadius (string, optional)
668
+ bottomRightRadius (string, optional)
669
+ bottomLeftRadius (string, optional)
670
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)
671
+ layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
672
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
673
+ paddingTop (string, optional)
674
+ paddingRight (string, optional)
675
+ paddingBottom (string, optional)
676
+ paddingLeft (string, optional)
677
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
678
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
679
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
680
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
681
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
682
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
683
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
684
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
685
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
686
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
687
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
688
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
689
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
690
+ annotations (array, optional) \u2014 Set annotations \u2014 [{label?, labelMarkdown?, properties?, categoryId?}]. Properties validated per node type.
691
+ componentId (string, optional) \u2014 Owning component ID. Optional \u2014 auto-resolved from parentId by walking up ancestors.`,
635
692
  "commit": '# frames.commit\nCommit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n\nExample: frames(method:"commit", id:"1:234")\n\nParams:\n id (string, required) \u2014 Staged node ID to commit',
636
693
  "export": "# frames.export\nExport a node as PNG, JPG, SVG, SVG_STRING, or PDF\n\nParams:\n id (string, required) \u2014 Node ID to export\n format (PNG | JPG | SVG | SVG_STRING | PDF, optional) \u2014 Export format (default: PNG). SVG_STRING returns raw SVG text.\n scale (number, optional) \u2014 Export scale (default: 1, only for PNG/JPG)"
637
694
  }
@@ -914,7 +971,7 @@ Methods:
914
971
  // "fixed-in-autolayout" \u2014 FIXED-size children in auto-layout parents [heuristic]
915
972
  // "unbounded-hug" \u2014 HUG on both axes [unsafe; short leaf text\u2192style]
916
973
  // "hug-cross-axis" \u2014 HUG on cross-axis of constrained parent [heuristic; leaf nodes\u2192style]
917
- // "empty-container" \u2014 empty frames [style]
974
+ // "empty-container" \u2014 empty frames, excludes SLOT nodes [style]
918
975
  // Token rules [token]:
919
976
  // "hardcoded-color" \u2014 colors not using styles or variables [heuristic]
920
977
  // "hardcoded-token" \u2014 numeric values not bound to FLOAT variable [heuristic]
@@ -1746,7 +1803,7 @@ var tools = [
1746
1803
  },
1747
1804
  {
1748
1805
  name: "frames",
1749
- description: '/** Create and manage frames, shapes, auto-layout containers, sections, and SVG nodes. Use method "help" for detailed parameter docs. */\n get (id, fields?, depth?, verbose?) \u2192 { results: Node[], _truncated?, _notice? } // Get serialized node data\n list (query?, types?, parentId?, fields?, offset?, limit?) \u2192 { totalCount, returned?, offset?, limit?, results } // Search for nodes (returns stubs only \u2014 use get with depth for full properties)\n update (items: PatchItem[]) \u2192 { results: ("ok" | {error})[] } // Patch node properties\n delete (id?, items?: { id?: string }[]) \u2192 { results: "ok"[] } // Delete nodes\n clone (id?, name?, parentId?, x?, y?, items?: { id: string; name?: string; parentId?: string; x?: number; y?: number }[], depth?) \u2192 { results: {id}[] } // Duplicate nodes \u2014 produces a same-type copy (frame\u2192frame, instance\u2192instance, component\u2192component). Instance clones reference the same source component; they do not duplicate the component definition.\n audit (id, rules?, maxDepth?, maxFindings?, minSeverity?: error|unsafe|heuristic|style|verbose, skipInstances?) \u2192 { nodeId?, nodeName?, categories? } // Run lint on a node \u2014 returns severity-ranked findings\n reparent (items: { id: string; parentId: string; index?: number }[]) \u2192 { results: "ok"[] } // Move nodes into a new parent\n create (type: frame|auto_layout|section|rectangle|ellipse|line|group|boolean_operation|svg, items: (FrameItem | AutoLayoutItem | SectionItem | RectangleItem | EllipseItem | LineItem | GroupItem | BooleanOperationItem | SvgItem)[]) \u2192 { results: {id}[] } // Create frame-like containers\n commit (id) \u2192 { results: {id}[] } // Commit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n export (id, format?: PNG|JPG|SVG|SVG_STRING|PDF, scale?) \u2192 { imageData?, mimeType? } // Export a node as PNG, JPG, SVG, SVG_STRING, or PDF\n// depth: omit \u2192 id+name stubs | 0 \u2192 props + child stubs | N \u2192 recurse N | -1 \u2192 full tree\n// fields: whitelist e.g. ["fills","opacity"] \u2014 id, name, type always included. Pass ["*"] for all.\n// layoutSizingHorizontal/Vertical: FIXED | HUG | FILL \u2014 how the node sizes within auto-layout.\n// Colors: fillVariableName/strokeVariableName bind by name \u2014 preferred over raw color values.\n// Note: node-based endpoints (frames, text, instances, components) use `results` as the list key.\n// Standalone endpoints (styles, variables, variable_collections) use `items`. Components.list uses `items` (catalog view).',
1806
+ description: '/** Create and manage frames, shapes, auto-layout containers, sections, and SVG nodes. Use method "help" for detailed parameter docs. */\n get (id, fields?, depth?, verbose?) \u2192 { results: Node[], _truncated?, _notice? } // Get serialized node data\n list (query?, types?, parentId?, fields?, offset?, limit?) \u2192 { totalCount, returned?, offset?, limit?, results } // Search for nodes (returns stubs only \u2014 use get with depth for full properties)\n update (items: PatchItem[]) \u2192 { results: ("ok" | {error})[] } // Patch node properties\n delete (id?, items?: { id?: string }[]) \u2192 { results: "ok"[] } // Delete nodes\n clone (id?, name?, parentId?, x?, y?, items?: { id: string; name?: string; parentId?: string; x?: number; y?: number }[], depth?) \u2192 { results: {id}[] } // Duplicate nodes \u2014 produces a same-type copy (frame\u2192frame, instance\u2192instance, component\u2192component). Instance clones reference the same source component; they do not duplicate the component definition.\n audit (id, rules?, maxDepth?, maxFindings?, minSeverity?: error|unsafe|heuristic|style|verbose, skipInstances?) \u2192 { nodeId?, nodeName?, categories? } // Run lint on a node \u2014 returns severity-ranked findings\n reparent (items: { id: string; parentId: string; index?: number }[]) \u2192 { results: "ok"[] } // Move nodes into a new parent\n create (type: frame|auto_layout|section|rectangle|ellipse|line|group|boolean_operation|svg|slot, items: (FrameItem | AutoLayoutItem | SectionItem | RectangleItem | EllipseItem | LineItem | GroupItem | BooleanOperationItem | SvgItem | SlotItem)[]) \u2192 { results: {id}[] } // Create frame-like containers\n commit (id) \u2192 { results: {id}[] } // Commit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n export (id, format?: PNG|JPG|SVG|SVG_STRING|PDF, scale?) \u2192 { imageData?, mimeType? } // Export a node as PNG, JPG, SVG, SVG_STRING, or PDF\n// depth: omit \u2192 id+name stubs | 0 \u2192 props + child stubs | N \u2192 recurse N | -1 \u2192 full tree\n// fields: whitelist e.g. ["fills","opacity"] \u2014 id, name, type always included. Pass ["*"] for all.\n// layoutSizingHorizontal/Vertical: FIXED | HUG | FILL \u2014 how the node sizes within auto-layout.\n// Colors: fillVariableName/strokeVariableName bind by name \u2014 preferred over raw color values.\n// Note: node-based endpoints (frames, text, instances, components) use `results` as the list key.\n// Standalone endpoints (styles, variables, variable_collections) use `items`. Components.list uses `items` (catalog view).',
1750
1807
  schema: (caps2) => filterMethodsByTier({
1751
1808
  method: import_zod4.z.enum(["get", "list", "update", "delete", "clone", "audit", "reparent", "create", "commit", "export", "help"]),
1752
1809
  id: import_zod4.z.string().optional().describe("Node ID"),
@@ -1767,7 +1824,7 @@ var tools = [
1767
1824
  maxFindings: import_zod4.z.coerce.number().optional().describe("Max findings (default: 50)"),
1768
1825
  minSeverity: import_zod4.z.enum(["error", "unsafe", "heuristic", "style", "verbose"]).optional().describe("Minimum severity to report (default: style). Set to 'verbose' to include AAA contrast and line-height checks."),
1769
1826
  skipInstances: flexBool(import_zod4.z.boolean()).optional().describe("Skip instance internals \u2014 findings inside instances are owned by the component (default: true)"),
1770
- type: import_zod4.z.enum(["frame", "auto_layout", "section", "rectangle", "ellipse", "line", "group", "boolean_operation", "svg"]).optional().describe("Discriminant for create method"),
1827
+ type: import_zod4.z.enum(["frame", "auto_layout", "section", "rectangle", "ellipse", "line", "group", "boolean_operation", "svg", "slot"]).optional().describe("Discriminant for create method"),
1771
1828
  format: import_zod4.z.enum(["PNG", "JPG", "SVG", "SVG_STRING", "PDF"]).optional().describe("Export format (default: PNG). SVG_STRING returns raw SVG text."),
1772
1829
  scale: import_zod4.z.coerce.number().optional().describe("Export scale (default: 1, only for PNG/JPG)"),
1773
1830
  topic: import_zod4.z.string().optional().describe('Help topic \u2014 method name for endpoint help, e.g. "create"')
@@ -2000,6 +2057,63 @@ var tools = [
2000
2057
  parentId: import_zod4.z.string().optional().describe("Parent node ID. Omit to place at current page root."),
2001
2058
  x: import_zod4.z.coerce.number().optional().describe("X position (default: 0)"),
2002
2059
  y: import_zod4.z.coerce.number().optional().describe("Y position (default: 0)")
2060
+ }).passthrough(),
2061
+ "slot": import_zod4.z.object({
2062
+ name: import_zod4.z.string().optional().describe("Node name"),
2063
+ parentId: import_zod4.z.string().optional().describe("Parent node ID inside the owning component. Required unless componentId is provided."),
2064
+ x: import_zod4.z.coerce.number().optional().describe("X position (default: 0)"),
2065
+ y: import_zod4.z.coerce.number().optional().describe("Y position (default: 0)"),
2066
+ width: import_zod4.z.coerce.number().optional().describe("Width in px (omit to shrink-to-content via HUG)"),
2067
+ height: import_zod4.z.coerce.number().optional().describe("Height in px (omit to shrink-to-content via HUG)"),
2068
+ rotation: import_zod4.z.coerce.number().optional().describe("Rotation in degrees (0-360)"),
2069
+ visible: flexBool(import_zod4.z.boolean()).optional().describe("Show/hide (default true)"),
2070
+ locked: flexBool(import_zod4.z.boolean()).optional().describe("Lock/unlock (default false)"),
2071
+ opacity: token.optional().describe("Opacity (0-1) or variable name"),
2072
+ blendMode: import_zod4.z.enum(["PASS_THROUGH", "NORMAL", "DARKEN", "MULTIPLY", "LINEAR_BURN", "COLOR_BURN", "LIGHTEN", "SCREEN", "LINEAR_DODGE", "COLOR_DODGE", "OVERLAY", "SOFT_LIGHT", "HARD_LIGHT", "DIFFERENCE", "EXCLUSION", "HUE", "SATURATION", "COLOR", "LUMINOSITY"]).optional(),
2073
+ effectStyleName: import_zod4.z.string().optional().describe("Effect style name (e.g. 'Shadow/Card') for shadows, blurs"),
2074
+ fills: import_zod4.z.array(import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown())).optional().describe("Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills."),
2075
+ fillColor: colorRgba.optional().describe("Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)"),
2076
+ fillStyleName: import_zod4.z.string().optional().describe("Paint style name for fill"),
2077
+ fillVariableName: import_zod4.z.string().optional().describe("Color variable by name e.g. 'bg/primary'"),
2078
+ imageUrl: import_zod4.z.string().optional().describe("Image source \u2014 'pexel:<id>' for Pexels photos, a public URL, or a local file path. SVGs are inserted as vectors; raster images become IMAGE fills."),
2079
+ imageScaleMode: import_zod4.z.enum(["FILL", "FIT", "CROP", "TILE"]).optional().describe("How the image is scaled within the frame (default: FILL)"),
2080
+ strokes: import_zod4.z.array(import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown())).optional().describe("Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes."),
2081
+ strokeColor: colorRgba.optional().describe("Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)"),
2082
+ strokeStyleName: import_zod4.z.string().optional().describe("Paint style name for stroke"),
2083
+ strokeVariableName: import_zod4.z.string().optional().describe("Color variable by name for stroke"),
2084
+ strokeWeight: token.optional().describe("All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight."),
2085
+ strokeTopWeight: token.optional(),
2086
+ strokeBottomWeight: token.optional(),
2087
+ strokeLeftWeight: token.optional(),
2088
+ strokeRightWeight: token.optional(),
2089
+ strokeAlign: import_zod4.z.enum(["INSIDE", "OUTSIDE", "CENTER"]).optional().describe("Stroke position (default: INSIDE)"),
2090
+ cornerRadius: token.optional().describe("All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius."),
2091
+ topLeftRadius: token.optional(),
2092
+ topRightRadius: token.optional(),
2093
+ bottomRightRadius: token.optional(),
2094
+ bottomLeftRadius: token.optional(),
2095
+ layoutMode: import_zod4.z.enum(["NONE", "HORIZONTAL", "VERTICAL"]).optional().describe("Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)"),
2096
+ layoutWrap: import_zod4.z.enum(["NO_WRAP", "WRAP"]).optional().describe("Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns."),
2097
+ padding: token.optional().describe("All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft."),
2098
+ paddingTop: token.optional(),
2099
+ paddingRight: token.optional(),
2100
+ paddingBottom: token.optional(),
2101
+ paddingLeft: token.optional(),
2102
+ primaryAxisAlignItems: import_zod4.z.enum(["MIN", "MAX", "CENTER", "SPACE_BETWEEN"]).optional(),
2103
+ counterAxisAlignItems: import_zod4.z.enum(["MIN", "MAX", "CENTER", "BASELINE"]).optional(),
2104
+ itemSpacing: token.optional().describe("Spacing between children (number or variable name string, default: 0)"),
2105
+ counterAxisSpacing: token.optional().describe("Gap between wrapped rows (requires layoutWrap: WRAP)"),
2106
+ strokesIncludedInLayout: flexBool(import_zod4.z.boolean()).optional().describe("Include stroke width in layout measurements (default: false)"),
2107
+ overflowDirection: import_zod4.z.enum(["NONE", "HORIZONTAL", "VERTICAL", "BOTH"]).optional().describe("Scroll overflow in prototype (default: NONE)"),
2108
+ layoutPositioning: import_zod4.z.enum(["AUTO", "ABSOLUTE"]).optional().describe("ABSOLUTE = floating inside auto-layout parent"),
2109
+ layoutSizingHorizontal: import_zod4.z.enum(["FIXED", "HUG", "FILL"]).optional(),
2110
+ layoutSizingVertical: import_zod4.z.enum(["FIXED", "HUG", "FILL"]).optional(),
2111
+ minWidth: import_zod4.z.coerce.number().optional().describe("Min width for responsive auto-layout"),
2112
+ maxWidth: import_zod4.z.coerce.number().optional().describe("Max width for responsive auto-layout"),
2113
+ minHeight: import_zod4.z.coerce.number().optional().describe("Min height for responsive auto-layout"),
2114
+ maxHeight: import_zod4.z.coerce.number().optional().describe("Max height for responsive auto-layout"),
2115
+ annotations: flexJson(import_zod4.z.array(import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()))).optional().describe("Set annotations \u2014 [{label?, labelMarkdown?, properties?, categoryId?}]. Properties validated per node type."),
2116
+ componentId: import_zod4.z.string().optional().describe("Owning component ID. Optional \u2014 auto-resolved from parentId by walking up ancestors.")
2003
2117
  }).passthrough()
2004
2118
  };
2005
2119
  const s = params.type && schemas[params.type];
@@ -3032,7 +3146,7 @@ var guidelinesList = [
3032
3146
  }
3033
3147
  ];
3034
3148
  var guidelinesContent = {
3035
- "component-structure": '# Component Structure\n\nComponents need correct sizing, property bindings, and token usage to work well as instances.\n\n## Width Constraints\n\nComponents with text content need a width \u2014 otherwise text never wraps.\n\n- Set `width` and `layoutSizingHorizontal:"FIXED"` on cards, panels, list items\n- HUG on both axes is only correct for buttons, badges, icons \u2014 intrinsically-sized elements\n\n## Property Bindings\n\nEvery text node inside a component should be bound to a TEXT property so instances can edit the content.\n\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- After creation: `frames(method:"update", items:[{id:"<textNodeId>", componentPropertyName:"<propName>"}])`\n- For existing nodes with many text children: `components(method:"create", type:"from_node", exposeText:true)`\n\nOrphaned properties (defined but not bound to any node) should be deleted:\n```\ncomponents(method:"update", items:[{id, propertyName:"<key>", action:"delete"}])\n```\n\n## Variant Sets\n\nGroup related components as variants \u2014 don\'t leave them as separate components.\n\n- Name variants with the property format: `Style=Primary`, `Style=Secondary`\n- Combine: `components(method:"create", type:"variant_set", items:[{componentIds:[...], name:"Button"}])`\n- Instances pick variants via `variantProperties:{"Style":"Primary"}`\n\n### Adding Variants to an Existing Set\n\nClone an existing variant into the same set with a new name. The `name` param is required \u2014 without it, the duplicate name corrupts the set.\n\n**Add a new value to an existing dimension** (e.g. State=Hover):\n```\ncomponents(method:"clone", id:"<variant_id>", name:"Style=Primary, State=Hover", parentId:"<set_id>")\n```\nClone one variant per combination. For a Style\xD7State set, adding State=Hover requires two clones (one per Style). Use batch `items` for efficiency:\n```\ncomponents(method:"clone", items:[\n {id:"<Primary/Default>", name:"Style=Primary, State=Hover", parentId:"<set_id>"},\n {id:"<Secondary/Default>", name:"Style=Secondary, State=Hover", parentId:"<set_id>"}\n])\n```\nThen patch the new variants: `frames(method:"update", items:[{id:"<new>", fillVariableName:"color/hover"}])`\n\n**Add a new dimension** (e.g. Size=sm to a Style\xD7State set):\n1. Batch rename existing variants to include the new dimension: `frames(method:"update", items:[{id:"<each>", name:"..., Size=md"}])`\n2. Batch clone all variants with the new value: `components(method:"clone", items:[{id:"<each>", name:"..., Size=sm", parentId:"<set_id>"}])`\n3. Batch patch the new variants: `frames(method:"update", items:[{id:"<each>", padding:8, minHeight:32}])`\n\nProperty bindings (TEXT, INSTANCE_SWAP) are preserved on cloned variants.\n\n## Checking\n\nRun `components(method:"audit", id)` \u2014 checks both lint rules and property bindings in one call.',
3149
+ "component-structure": '# Component Structure\n\nComponents need correct sizing, property bindings, and token usage to work well as instances.\n\n## Width Constraints\n\nComponents with text content need a width \u2014 otherwise text never wraps.\n\n- Set `width` and `layoutSizingHorizontal:"FIXED"` on cards, panels, list items\n- HUG on both axes is only correct for buttons, badges, icons \u2014 intrinsically-sized elements\n\n## Property Bindings\n\nEvery text node inside a component should be bound to a TEXT property so instances can edit the content.\n\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- After creation: `frames(method:"update", items:[{id:"<textNodeId>", componentPropertyName:"<propName>"}])`\n- For existing nodes with many text children: `components(method:"create", type:"from_node", exposeText:true)`\n\nOrphaned properties (defined but not bound to any node) should be deleted:\n```\ncomponents(method:"update", items:[{id, propertyName:"<key>", action:"delete"}])\n```\n\n## Variant Sets\n\nGroup related components as variants \u2014 don\'t leave them as separate components.\n\n- Name variants with the property format: `Style=Primary`, `Style=Secondary`\n- Combine: `components(method:"create", type:"variant_set", items:[{componentIds:[...], name:"Button"}])`\n- Instances pick variants via `variantProperties:{"Style":"Primary"}`\n\n### Adding Variants to an Existing Set\n\nClone an existing variant into the same set with a new name. The `name` param is required \u2014 without it, the duplicate name corrupts the set.\n\n**Add a new value to an existing dimension** (e.g. State=Hover):\n```\ncomponents(method:"clone", id:"<variant_id>", name:"Style=Primary, State=Hover", parentId:"<set_id>")\n```\nClone one variant per combination. For a Style\xD7State set, adding State=Hover requires two clones (one per Style). Use batch `items` for efficiency:\n```\ncomponents(method:"clone", items:[\n {id:"<Primary/Default>", name:"Style=Primary, State=Hover", parentId:"<set_id>"},\n {id:"<Secondary/Default>", name:"Style=Secondary, State=Hover", parentId:"<set_id>"}\n])\n```\nThen patch the new variants: `frames(method:"update", items:[{id:"<new>", fillVariableName:"color/hover"}])`\n\n**Add a new dimension** (e.g. Size=sm to a Style\xD7State set):\n1. Batch rename existing variants to include the new dimension: `frames(method:"update", items:[{id:"<each>", name:"..., Size=md"}])`\n2. Batch clone all variants with the new value: `components(method:"clone", items:[{id:"<each>", name:"..., Size=sm", parentId:"<set_id>"}])`\n3. Batch patch the new variants: `frames(method:"update", items:[{id:"<each>", padding:8, minHeight:32}])`\n\nProperty bindings (TEXT, INSTANCE_SWAP) are preserved on cloned variants.\n\n## Slots\n\nSlots are placeholder containers inside components that instance users can fill with custom content.\n\n- Create at component root: `frames(method:"create", type:"slot", items:[{parentId:"<comp_id>", name:"Content"}])`\n- Create nested inside a frame within a component: `frames(method:"create", type:"slot", items:[{parentId:"<frame_id>", name:"Content"}])`\n- In instances, add content by using the slot\'s ID as `parentId` on any create/reparent call\n- Empty slots are normal \u2014 they don\'t trigger lint warnings\n\n## Checking\n\nRun `components(method:"audit", id)` \u2014 checks both lint rules and property bindings in one call.',
3036
3150
  "library-components": '# Working with Library Components\n\nLibrary components are read-only \u2014 they come from external team libraries and cannot be edited in the current file.\n\n## Reading\n\nWhen reading nodes, library instances appear as stubs with their overridable properties:\n```\n{name: "Header", type: "INSTANCE", componentProperties: {"Platform": "Desktop"}}\n```\n\nLibrary internals are hidden: no `componentId`, no variable names, no style names. You see resolved values (hex colors, numbers) instead.\n\n## Using\n\nPlace library instances via `instances(method:"create", items:[{componentId:"<id>"}])` when you have a local component ID. For library components, instances are already placed by the designer \u2014 interact via `instances(method:"update")` to set properties.\n\n## Customizing\n\nTo edit a library component, clone it into the local file first:\n\n```\ncomponents(method:"clone", id:"<instanceId>")\n```\n\nThis resolves the instance to its source component (or full component set) and creates a local copy with a new ID. Edit the local copy freely \u2014 it is independent of the library.\n\nDo not attempt to `components(method:"get")` or `components(method:"update")` a library component directly \u2014 these will error.\n\n## Overriding Instance Properties\n\nUse `instances(method:"update")` to change overridable properties on library instances:\n```\ninstances(method:"update", items:[{id:"<instanceId>", properties:{"Label":"New Text", "State":"Hover"}}])\n```\n\nProperty names are clean (no hash suffixes needed for update \u2014 the system resolves partial keys).',
3037
3151
  "responsive-designs": '# Responsive Sizing\n\n## Workflow: Top-Down Sizing\n\nBuild layouts from the outside in:\n\n1. **Set the container first.** Every container needs an explicit width \u2014 either `width` + `layoutSizingHorizontal:"FIXED"` for shells and bounded panels, or `layoutSizingHorizontal:"FILL"` inside an auto-layout parent. Set `layoutMode` (VERTICAL or HORIZONTAL) and spacing/padding.\n2. **Children fill the container.** Use `layoutSizingHorizontal:"FILL"` on children so they stretch to the available space. Use `layoutSizingVertical:"HUG"` so height follows content.\n3. **Only leaves use HUG on both axes.** Buttons, badges, icons \u2014 elements with short, predictable content that should shrink-wrap.\n\nThis ensures every level of the tree has a clear width constraint. Text wraps, FILL children stretch, and the layout adapts when the container resizes.\n\nAlways set BOTH axes explicitly on every node. Omitting sizing leads to unintended defaults.\n\n## FIXED / FILL / HUG\n\n- **FIXED** \u2014 explicit bounded widths: page shell, sidebar, modal max-width, specimen frames\n- **FILL** \u2014 children that adapt to parent: cards, rows, panels, nav stacks, text that should wrap. Use `minWidth`/`maxWidth` for responsive constraints.\n- **HUG** \u2014 content-sized leaves only: icons, badges, pills, button labels\n\n## Anti-patterns: HUG/HUG\n\nHUG on both axes is the most common cause of broken layouts. It means "shrink to fit my content on both axes" \u2014 the container has no opinion about its own size and collapses to whatever its children measure.\n\n**Why HUG/HUG breaks designs:**\n\n1. **Text never wraps.** A HUG-width container grows to fit the longest text line. Body text becomes a single very long line instead of wrapping at a readable width. The design looks correct with short placeholder text but breaks with real content.\n\n2. **Layouts don\'t adapt.** HUG/HUG containers ignore their parent\'s width. A card inside a responsive column won\'t stretch to fill available space \u2014 it stays at its content width, leaving gaps or overflowing.\n\n3. **FILL children become under-constrained.** A child with `layoutSizingHorizontal:"FILL"` inside a HUG-width parent has no space to fill \u2014 the parent defers its width to its children, but the FILL child defers its width to the parent. The result is under-constrained sizing that produces unpredictable or collapsed layouts.\n\n4. **Cascading failures.** One HUG/HUG container at the top of a tree forces every child to resolve its own width. The entire layout becomes rigid and content-dependent instead of responsive.\n\n**HUG/HUG is only correct for:**\n- Buttons, pills, badges, chips \u2014 intrinsically-sized leaf elements with short, predictable content\n- Icon containers with fixed-size children\n- Inline tags and status indicators\n\n**For everything else, set at least one axis to FIXED or FILL:**\n- Cards, panels, list rows \u2192 `layoutSizingHorizontal:"FILL"`, vertical `HUG`. Add `minWidth`/`maxWidth` for responsive bounds.\n- Shells, sidebars, modals \u2192 `width` + `layoutSizingHorizontal:"FIXED"`, vertical `FILL` or `HUG`\n- Full-width sections \u2192 `layoutSizingHorizontal:"FILL"`, `layoutSizingVertical:"HUG"`\n\n## Wrapping Layouts (layoutWrap)\n\n`layoutWrap: WRAP` enables children to flow into new rows when they exceed the container width \u2014 like CSS `flex-wrap`. This only works with **HORIZONTAL** auto-layout. Figma does not support wrap on VERTICAL layouts.\n\n**When to use wrap:**\n- Card grids with a fixed number of columns at a known width\n- Tag/chip collections where items flow into multiple rows\n- Any layout where items should reflow based on available width\n\n**Horizontal wrap pattern:**\n```\nframes.create(type: "auto_layout", layoutMode: "HORIZONTAL", layoutWrap: "WRAP",\n itemSpacing: "space/16", counterAxisSpacing: "space/16")\n```\nChildren use FIXED width to control column count. `counterAxisSpacing` sets the gap between wrapped rows.\n\n**Vertical grid alternative:**\nSince VERTICAL layouts cannot wrap, build column-based grids by nesting VERTICAL columns inside a HORIZONTAL parent:\n```\nouter (HORIZONTAL, itemSpacing: 20, FILL width)\n col-1 (VERTICAL, FILL width, HUG height, itemSpacing: 20)\n col-2 (VERTICAL, FILL width, HUG height, itemSpacing: 20)\n col-3 (VERTICAL, FILL width, HUG height, itemSpacing: 20)\n```\nEach column gets equal width via FILL. Reparent items into columns for column-first ordering. This handles variable card heights per column independently.\n\n## Component Sizing\n\nComponent roots use `FILL` when placed in a parent \u2014 they adapt to context, not a fixed specimen width. Use `FIXED` only for the specimen (the component definition itself when it needs a specific preview width).\n\nExample sidebar item:\n- Instance: `FILL` in parent nav stack\n- Icon child: fixed 18x18\n- Label child: `FILL`\n- Badge child: `HUG`\n\n## Text Sizing\n\n- Body text inside containers: prefer `FILL` width, `HUG` height (auto-wraps)\n- Single-line labels: prefer `FILL` horizontal (truncates if needed)\n- Standalone headings: `HUG` is fine\n\nInside auto-layout parents, target `layoutSizingHorizontal:"FILL"` + `layoutSizingVertical:"HUG"` + `textAutoResize:"HEIGHT"` for text that should wrap. These are not auto-applied \u2014 set them explicitly on text.create or text.update.\n\n## Checklist\n\nBefore finalizing a layout, verify:\n1. No container with text has HUG on the horizontal axis (unless it\'s a button/badge)\n2. Children use FILL on the axis that should absorb available space \u2014 not blindly on both axes. Compact controls in horizontal rows often stay HUG vertically.\n3. Top-level containers have an explicit width (FIXED) or stretch to their parent (FILL)\n4. Run `lint(method:"check", nodeId:"<rootId>", rules:["composition"])` to catch overflow-parent, unbounded-hug, and fixed-in-autolayout issues',
3038
3152
  "token-discipline": '# Token Discipline\n\nEvery color, spacing value, and text style should come from a design token \u2014 not hardcoded values.\n\n## Colors\n\nBind fills and strokes to color variables instead of hex values.\n\n- Fill: `fillVariableName:"bg/primary"` or `fillStyleName:"Surface/Primary"`\n- Stroke: `strokeVariableName:"border/default"`\n- Text color: `fontColorVariableName:"text/primary"`\n\nIf no matching variable exists, create one first:\n```\nvariables(method:"create", collectionId:"Colors", items:[{name:"bg/accent", type:"COLOR", valuesByMode:{"Light":"#E8F0FE","Dark":"#1A3A5C"}, scopes:["ALL_FILLS"]}])\n```\n\n## Spacing and Radius\n\nPass a variable name string instead of a number for cornerRadius, padding, itemSpacing, strokeWeight, opacity.\n\n- `cornerRadius:"radius/8"` not `cornerRadius:8`\n- `paddingTop:"space/16"` not `paddingTop:16`\n- `itemSpacing:"space/8"` not `itemSpacing:8`\n\nCreate FLOAT variables with appropriate scopes:\n```\nvariables(method:"create", collectionId:"Metrics", items:[{name:"space/12", type:"FLOAT", value:12, scopes:["GAP","WIDTH_HEIGHT"]}])\n```\n\n## Text Styles\n\nApply text styles by name \u2014 don\'t set fontSize/fontFamily/fontWeight manually.\n\n- `textStyleName:"Body/M"` on text.create or frames.update\n- Create styles with `styles(method:"create", type:"text", items:[{name:"Body/M", fontFamily:"Inter", fontSize:14, lineHeight:{value:20, unit:"PIXELS"}}])`\n\n## Common Scopes\n\nCOLOR variables:\n- `ALL_FILLS` \u2014 background fills\n- `TEXT_FILL` \u2014 text color\n- `STROKE_COLOR` \u2014 borders and outlines\n\nFLOAT variables:\n- `GAP`, `WIDTH_HEIGHT` \u2014 spacing and padding\n- `CORNER_RADIUS` \u2014 border radius\n- `STROKE_FLOAT` \u2014 stroke weight\n- `OPACITY` \u2014 transparency\n\n## Checking\n\nLint rules `hardcoded-color`, `hardcoded-token`, `no-text-style` catch unbound values. Run `audit` on any node to check.',
package/dist/mcp.js CHANGED
@@ -390,7 +390,7 @@ Create frame-like containers
390
390
 
391
391
  Example: frames(method:"create", type:"auto_layout", layoutMode:"VERTICAL", itemSpacing:16, padding:24)
392
392
 
393
- Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line | group | boolean_operation | svg)
393
+ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line | group | boolean_operation | svg | slot)
394
394
 
395
395
  ## frame \u2014 General-purpose frame \u2014 shrinks to content by default, static when width+height given
396
396
  name (string, optional) \u2014 Node name
@@ -609,7 +609,64 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
609
609
  name (string, optional) \u2014 Layer name (default: 'SVG')
610
610
  parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
611
611
  x (number, optional) \u2014 X position (default: 0)
612
- y (number, optional) \u2014 Y position (default: 0)`,
612
+ y (number, optional) \u2014 Y position (default: 0)
613
+
614
+ ## slot \u2014 Create a slot inside a component. Slots are placeholder containers that instance users fill with content. Defaults to VERTICAL auto-layout with FILL/HUG sizing \u2014 ready to receive children. Accepts all frame layout properties.
615
+ name (string, optional) \u2014 Node name
616
+ parentId (string, optional) \u2014 Parent node ID inside the owning component. Required unless componentId is provided.
617
+ x (number, optional) \u2014 X position (default: 0)
618
+ y (number, optional) \u2014 Y position (default: 0)
619
+ width (number, optional) \u2014 Width in px (omit to shrink-to-content via HUG)
620
+ height (number, optional) \u2014 Height in px (omit to shrink-to-content via HUG)
621
+ rotation (number, optional) \u2014 Rotation in degrees (0-360)
622
+ visible (boolean, optional) \u2014 Show/hide (default true)
623
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
624
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
625
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
626
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
627
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
628
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
629
+ fillStyleName (string, optional) \u2014 Paint style name for fill
630
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
631
+ imageUrl (string, optional) \u2014 Image source \u2014 'pexel:<id>' for Pexels photos, a public URL, or a local file path. SVGs are inserted as vectors; raster images become IMAGE fills.
632
+ imageScaleMode (FILL | FIT | CROP | TILE, optional) \u2014 How the image is scaled within the frame (default: FILL)
633
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
634
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
635
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
636
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
637
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
638
+ strokeTopWeight (string, optional)
639
+ strokeBottomWeight (string, optional)
640
+ strokeLeftWeight (string, optional)
641
+ strokeRightWeight (string, optional)
642
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
643
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
644
+ topLeftRadius (string, optional)
645
+ topRightRadius (string, optional)
646
+ bottomRightRadius (string, optional)
647
+ bottomLeftRadius (string, optional)
648
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)
649
+ layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
650
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
651
+ paddingTop (string, optional)
652
+ paddingRight (string, optional)
653
+ paddingBottom (string, optional)
654
+ paddingLeft (string, optional)
655
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
656
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
657
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
658
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
659
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
660
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
661
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
662
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
663
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
664
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
665
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
666
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
667
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
668
+ annotations (array, optional) \u2014 Set annotations \u2014 [{label?, labelMarkdown?, properties?, categoryId?}]. Properties validated per node type.
669
+ componentId (string, optional) \u2014 Owning component ID. Optional \u2014 auto-resolved from parentId by walking up ancestors.`,
613
670
  "commit": '# frames.commit\nCommit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n\nExample: frames(method:"commit", id:"1:234")\n\nParams:\n id (string, required) \u2014 Staged node ID to commit',
614
671
  "export": "# frames.export\nExport a node as PNG, JPG, SVG, SVG_STRING, or PDF\n\nParams:\n id (string, required) \u2014 Node ID to export\n format (PNG | JPG | SVG | SVG_STRING | PDF, optional) \u2014 Export format (default: PNG). SVG_STRING returns raw SVG text.\n scale (number, optional) \u2014 Export scale (default: 1, only for PNG/JPG)"
615
672
  }
@@ -892,7 +949,7 @@ Methods:
892
949
  // "fixed-in-autolayout" \u2014 FIXED-size children in auto-layout parents [heuristic]
893
950
  // "unbounded-hug" \u2014 HUG on both axes [unsafe; short leaf text\u2192style]
894
951
  // "hug-cross-axis" \u2014 HUG on cross-axis of constrained parent [heuristic; leaf nodes\u2192style]
895
- // "empty-container" \u2014 empty frames [style]
952
+ // "empty-container" \u2014 empty frames, excludes SLOT nodes [style]
896
953
  // Token rules [token]:
897
954
  // "hardcoded-color" \u2014 colors not using styles or variables [heuristic]
898
955
  // "hardcoded-token" \u2014 numeric values not bound to FLOAT variable [heuristic]
@@ -1724,7 +1781,7 @@ var tools = [
1724
1781
  },
1725
1782
  {
1726
1783
  name: "frames",
1727
- description: '/** Create and manage frames, shapes, auto-layout containers, sections, and SVG nodes. Use method "help" for detailed parameter docs. */\n get (id, fields?, depth?, verbose?) \u2192 { results: Node[], _truncated?, _notice? } // Get serialized node data\n list (query?, types?, parentId?, fields?, offset?, limit?) \u2192 { totalCount, returned?, offset?, limit?, results } // Search for nodes (returns stubs only \u2014 use get with depth for full properties)\n update (items: PatchItem[]) \u2192 { results: ("ok" | {error})[] } // Patch node properties\n delete (id?, items?: { id?: string }[]) \u2192 { results: "ok"[] } // Delete nodes\n clone (id?, name?, parentId?, x?, y?, items?: { id: string; name?: string; parentId?: string; x?: number; y?: number }[], depth?) \u2192 { results: {id}[] } // Duplicate nodes \u2014 produces a same-type copy (frame\u2192frame, instance\u2192instance, component\u2192component). Instance clones reference the same source component; they do not duplicate the component definition.\n audit (id, rules?, maxDepth?, maxFindings?, minSeverity?: error|unsafe|heuristic|style|verbose, skipInstances?) \u2192 { nodeId?, nodeName?, categories? } // Run lint on a node \u2014 returns severity-ranked findings\n reparent (items: { id: string; parentId: string; index?: number }[]) \u2192 { results: "ok"[] } // Move nodes into a new parent\n create (type: frame|auto_layout|section|rectangle|ellipse|line|group|boolean_operation|svg, items: (FrameItem | AutoLayoutItem | SectionItem | RectangleItem | EllipseItem | LineItem | GroupItem | BooleanOperationItem | SvgItem)[]) \u2192 { results: {id}[] } // Create frame-like containers\n commit (id) \u2192 { results: {id}[] } // Commit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n export (id, format?: PNG|JPG|SVG|SVG_STRING|PDF, scale?) \u2192 { imageData?, mimeType? } // Export a node as PNG, JPG, SVG, SVG_STRING, or PDF\n// depth: omit \u2192 id+name stubs | 0 \u2192 props + child stubs | N \u2192 recurse N | -1 \u2192 full tree\n// fields: whitelist e.g. ["fills","opacity"] \u2014 id, name, type always included. Pass ["*"] for all.\n// layoutSizingHorizontal/Vertical: FIXED | HUG | FILL \u2014 how the node sizes within auto-layout.\n// Colors: fillVariableName/strokeVariableName bind by name \u2014 preferred over raw color values.\n// Note: node-based endpoints (frames, text, instances, components) use `results` as the list key.\n// Standalone endpoints (styles, variables, variable_collections) use `items`. Components.list uses `items` (catalog view).',
1784
+ description: '/** Create and manage frames, shapes, auto-layout containers, sections, and SVG nodes. Use method "help" for detailed parameter docs. */\n get (id, fields?, depth?, verbose?) \u2192 { results: Node[], _truncated?, _notice? } // Get serialized node data\n list (query?, types?, parentId?, fields?, offset?, limit?) \u2192 { totalCount, returned?, offset?, limit?, results } // Search for nodes (returns stubs only \u2014 use get with depth for full properties)\n update (items: PatchItem[]) \u2192 { results: ("ok" | {error})[] } // Patch node properties\n delete (id?, items?: { id?: string }[]) \u2192 { results: "ok"[] } // Delete nodes\n clone (id?, name?, parentId?, x?, y?, items?: { id: string; name?: string; parentId?: string; x?: number; y?: number }[], depth?) \u2192 { results: {id}[] } // Duplicate nodes \u2014 produces a same-type copy (frame\u2192frame, instance\u2192instance, component\u2192component). Instance clones reference the same source component; they do not duplicate the component definition.\n audit (id, rules?, maxDepth?, maxFindings?, minSeverity?: error|unsafe|heuristic|style|verbose, skipInstances?) \u2192 { nodeId?, nodeName?, categories? } // Run lint on a node \u2014 returns severity-ranked findings\n reparent (items: { id: string; parentId: string; index?: number }[]) \u2192 { results: "ok"[] } // Move nodes into a new parent\n create (type: frame|auto_layout|section|rectangle|ellipse|line|group|boolean_operation|svg|slot, items: (FrameItem | AutoLayoutItem | SectionItem | RectangleItem | EllipseItem | LineItem | GroupItem | BooleanOperationItem | SvgItem | SlotItem)[]) \u2192 { results: {id}[] } // Create frame-like containers\n commit (id) \u2192 { results: {id}[] } // Commit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n export (id, format?: PNG|JPG|SVG|SVG_STRING|PDF, scale?) \u2192 { imageData?, mimeType? } // Export a node as PNG, JPG, SVG, SVG_STRING, or PDF\n// depth: omit \u2192 id+name stubs | 0 \u2192 props + child stubs | N \u2192 recurse N | -1 \u2192 full tree\n// fields: whitelist e.g. ["fills","opacity"] \u2014 id, name, type always included. Pass ["*"] for all.\n// layoutSizingHorizontal/Vertical: FIXED | HUG | FILL \u2014 how the node sizes within auto-layout.\n// Colors: fillVariableName/strokeVariableName bind by name \u2014 preferred over raw color values.\n// Note: node-based endpoints (frames, text, instances, components) use `results` as the list key.\n// Standalone endpoints (styles, variables, variable_collections) use `items`. Components.list uses `items` (catalog view).',
1728
1785
  schema: (caps2) => filterMethodsByTier({
1729
1786
  method: z3.enum(["get", "list", "update", "delete", "clone", "audit", "reparent", "create", "commit", "export", "help"]),
1730
1787
  id: z3.string().optional().describe("Node ID"),
@@ -1745,7 +1802,7 @@ var tools = [
1745
1802
  maxFindings: z3.coerce.number().optional().describe("Max findings (default: 50)"),
1746
1803
  minSeverity: z3.enum(["error", "unsafe", "heuristic", "style", "verbose"]).optional().describe("Minimum severity to report (default: style). Set to 'verbose' to include AAA contrast and line-height checks."),
1747
1804
  skipInstances: flexBool(z3.boolean()).optional().describe("Skip instance internals \u2014 findings inside instances are owned by the component (default: true)"),
1748
- type: z3.enum(["frame", "auto_layout", "section", "rectangle", "ellipse", "line", "group", "boolean_operation", "svg"]).optional().describe("Discriminant for create method"),
1805
+ type: z3.enum(["frame", "auto_layout", "section", "rectangle", "ellipse", "line", "group", "boolean_operation", "svg", "slot"]).optional().describe("Discriminant for create method"),
1749
1806
  format: z3.enum(["PNG", "JPG", "SVG", "SVG_STRING", "PDF"]).optional().describe("Export format (default: PNG). SVG_STRING returns raw SVG text."),
1750
1807
  scale: z3.coerce.number().optional().describe("Export scale (default: 1, only for PNG/JPG)"),
1751
1808
  topic: z3.string().optional().describe('Help topic \u2014 method name for endpoint help, e.g. "create"')
@@ -1978,6 +2035,63 @@ var tools = [
1978
2035
  parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
1979
2036
  x: z3.coerce.number().optional().describe("X position (default: 0)"),
1980
2037
  y: z3.coerce.number().optional().describe("Y position (default: 0)")
2038
+ }).passthrough(),
2039
+ "slot": z3.object({
2040
+ name: z3.string().optional().describe("Node name"),
2041
+ parentId: z3.string().optional().describe("Parent node ID inside the owning component. Required unless componentId is provided."),
2042
+ x: z3.coerce.number().optional().describe("X position (default: 0)"),
2043
+ y: z3.coerce.number().optional().describe("Y position (default: 0)"),
2044
+ width: z3.coerce.number().optional().describe("Width in px (omit to shrink-to-content via HUG)"),
2045
+ height: z3.coerce.number().optional().describe("Height in px (omit to shrink-to-content via HUG)"),
2046
+ rotation: z3.coerce.number().optional().describe("Rotation in degrees (0-360)"),
2047
+ visible: flexBool(z3.boolean()).optional().describe("Show/hide (default true)"),
2048
+ locked: flexBool(z3.boolean()).optional().describe("Lock/unlock (default false)"),
2049
+ opacity: token.optional().describe("Opacity (0-1) or variable name"),
2050
+ blendMode: z3.enum(["PASS_THROUGH", "NORMAL", "DARKEN", "MULTIPLY", "LINEAR_BURN", "COLOR_BURN", "LIGHTEN", "SCREEN", "LINEAR_DODGE", "COLOR_DODGE", "OVERLAY", "SOFT_LIGHT", "HARD_LIGHT", "DIFFERENCE", "EXCLUSION", "HUE", "SATURATION", "COLOR", "LUMINOSITY"]).optional(),
2051
+ effectStyleName: z3.string().optional().describe("Effect style name (e.g. 'Shadow/Card') for shadows, blurs"),
2052
+ fills: z3.array(z3.record(z3.string(), z3.unknown())).optional().describe("Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills."),
2053
+ fillColor: colorRgba.optional().describe("Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)"),
2054
+ fillStyleName: z3.string().optional().describe("Paint style name for fill"),
2055
+ fillVariableName: z3.string().optional().describe("Color variable by name e.g. 'bg/primary'"),
2056
+ imageUrl: z3.string().optional().describe("Image source \u2014 'pexel:<id>' for Pexels photos, a public URL, or a local file path. SVGs are inserted as vectors; raster images become IMAGE fills."),
2057
+ imageScaleMode: z3.enum(["FILL", "FIT", "CROP", "TILE"]).optional().describe("How the image is scaled within the frame (default: FILL)"),
2058
+ strokes: z3.array(z3.record(z3.string(), z3.unknown())).optional().describe("Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes."),
2059
+ strokeColor: colorRgba.optional().describe("Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)"),
2060
+ strokeStyleName: z3.string().optional().describe("Paint style name for stroke"),
2061
+ strokeVariableName: z3.string().optional().describe("Color variable by name for stroke"),
2062
+ strokeWeight: token.optional().describe("All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight."),
2063
+ strokeTopWeight: token.optional(),
2064
+ strokeBottomWeight: token.optional(),
2065
+ strokeLeftWeight: token.optional(),
2066
+ strokeRightWeight: token.optional(),
2067
+ strokeAlign: z3.enum(["INSIDE", "OUTSIDE", "CENTER"]).optional().describe("Stroke position (default: INSIDE)"),
2068
+ cornerRadius: token.optional().describe("All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius."),
2069
+ topLeftRadius: token.optional(),
2070
+ topRightRadius: token.optional(),
2071
+ bottomRightRadius: token.optional(),
2072
+ bottomLeftRadius: token.optional(),
2073
+ layoutMode: z3.enum(["NONE", "HORIZONTAL", "VERTICAL"]).optional().describe("Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)"),
2074
+ layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional().describe("Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns."),
2075
+ padding: token.optional().describe("All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft."),
2076
+ paddingTop: token.optional(),
2077
+ paddingRight: token.optional(),
2078
+ paddingBottom: token.optional(),
2079
+ paddingLeft: token.optional(),
2080
+ primaryAxisAlignItems: z3.enum(["MIN", "MAX", "CENTER", "SPACE_BETWEEN"]).optional(),
2081
+ counterAxisAlignItems: z3.enum(["MIN", "MAX", "CENTER", "BASELINE"]).optional(),
2082
+ itemSpacing: token.optional().describe("Spacing between children (number or variable name string, default: 0)"),
2083
+ counterAxisSpacing: token.optional().describe("Gap between wrapped rows (requires layoutWrap: WRAP)"),
2084
+ strokesIncludedInLayout: flexBool(z3.boolean()).optional().describe("Include stroke width in layout measurements (default: false)"),
2085
+ overflowDirection: z3.enum(["NONE", "HORIZONTAL", "VERTICAL", "BOTH"]).optional().describe("Scroll overflow in prototype (default: NONE)"),
2086
+ layoutPositioning: z3.enum(["AUTO", "ABSOLUTE"]).optional().describe("ABSOLUTE = floating inside auto-layout parent"),
2087
+ layoutSizingHorizontal: z3.enum(["FIXED", "HUG", "FILL"]).optional(),
2088
+ layoutSizingVertical: z3.enum(["FIXED", "HUG", "FILL"]).optional(),
2089
+ minWidth: z3.coerce.number().optional().describe("Min width for responsive auto-layout"),
2090
+ maxWidth: z3.coerce.number().optional().describe("Max width for responsive auto-layout"),
2091
+ minHeight: z3.coerce.number().optional().describe("Min height for responsive auto-layout"),
2092
+ maxHeight: z3.coerce.number().optional().describe("Max height for responsive auto-layout"),
2093
+ annotations: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe("Set annotations \u2014 [{label?, labelMarkdown?, properties?, categoryId?}]. Properties validated per node type."),
2094
+ componentId: z3.string().optional().describe("Owning component ID. Optional \u2014 auto-resolved from parentId by walking up ancestors.")
1981
2095
  }).passthrough()
1982
2096
  };
1983
2097
  const s = params.type && schemas[params.type];
@@ -3010,7 +3124,7 @@ var guidelinesList = [
3010
3124
  }
3011
3125
  ];
3012
3126
  var guidelinesContent = {
3013
- "component-structure": '# Component Structure\n\nComponents need correct sizing, property bindings, and token usage to work well as instances.\n\n## Width Constraints\n\nComponents with text content need a width \u2014 otherwise text never wraps.\n\n- Set `width` and `layoutSizingHorizontal:"FIXED"` on cards, panels, list items\n- HUG on both axes is only correct for buttons, badges, icons \u2014 intrinsically-sized elements\n\n## Property Bindings\n\nEvery text node inside a component should be bound to a TEXT property so instances can edit the content.\n\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- After creation: `frames(method:"update", items:[{id:"<textNodeId>", componentPropertyName:"<propName>"}])`\n- For existing nodes with many text children: `components(method:"create", type:"from_node", exposeText:true)`\n\nOrphaned properties (defined but not bound to any node) should be deleted:\n```\ncomponents(method:"update", items:[{id, propertyName:"<key>", action:"delete"}])\n```\n\n## Variant Sets\n\nGroup related components as variants \u2014 don\'t leave them as separate components.\n\n- Name variants with the property format: `Style=Primary`, `Style=Secondary`\n- Combine: `components(method:"create", type:"variant_set", items:[{componentIds:[...], name:"Button"}])`\n- Instances pick variants via `variantProperties:{"Style":"Primary"}`\n\n### Adding Variants to an Existing Set\n\nClone an existing variant into the same set with a new name. The `name` param is required \u2014 without it, the duplicate name corrupts the set.\n\n**Add a new value to an existing dimension** (e.g. State=Hover):\n```\ncomponents(method:"clone", id:"<variant_id>", name:"Style=Primary, State=Hover", parentId:"<set_id>")\n```\nClone one variant per combination. For a Style\xD7State set, adding State=Hover requires two clones (one per Style). Use batch `items` for efficiency:\n```\ncomponents(method:"clone", items:[\n {id:"<Primary/Default>", name:"Style=Primary, State=Hover", parentId:"<set_id>"},\n {id:"<Secondary/Default>", name:"Style=Secondary, State=Hover", parentId:"<set_id>"}\n])\n```\nThen patch the new variants: `frames(method:"update", items:[{id:"<new>", fillVariableName:"color/hover"}])`\n\n**Add a new dimension** (e.g. Size=sm to a Style\xD7State set):\n1. Batch rename existing variants to include the new dimension: `frames(method:"update", items:[{id:"<each>", name:"..., Size=md"}])`\n2. Batch clone all variants with the new value: `components(method:"clone", items:[{id:"<each>", name:"..., Size=sm", parentId:"<set_id>"}])`\n3. Batch patch the new variants: `frames(method:"update", items:[{id:"<each>", padding:8, minHeight:32}])`\n\nProperty bindings (TEXT, INSTANCE_SWAP) are preserved on cloned variants.\n\n## Checking\n\nRun `components(method:"audit", id)` \u2014 checks both lint rules and property bindings in one call.',
3127
+ "component-structure": '# Component Structure\n\nComponents need correct sizing, property bindings, and token usage to work well as instances.\n\n## Width Constraints\n\nComponents with text content need a width \u2014 otherwise text never wraps.\n\n- Set `width` and `layoutSizingHorizontal:"FIXED"` on cards, panels, list items\n- HUG on both axes is only correct for buttons, badges, icons \u2014 intrinsically-sized elements\n\n## Property Bindings\n\nEvery text node inside a component should be bound to a TEXT property so instances can edit the content.\n\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- After creation: `frames(method:"update", items:[{id:"<textNodeId>", componentPropertyName:"<propName>"}])`\n- For existing nodes with many text children: `components(method:"create", type:"from_node", exposeText:true)`\n\nOrphaned properties (defined but not bound to any node) should be deleted:\n```\ncomponents(method:"update", items:[{id, propertyName:"<key>", action:"delete"}])\n```\n\n## Variant Sets\n\nGroup related components as variants \u2014 don\'t leave them as separate components.\n\n- Name variants with the property format: `Style=Primary`, `Style=Secondary`\n- Combine: `components(method:"create", type:"variant_set", items:[{componentIds:[...], name:"Button"}])`\n- Instances pick variants via `variantProperties:{"Style":"Primary"}`\n\n### Adding Variants to an Existing Set\n\nClone an existing variant into the same set with a new name. The `name` param is required \u2014 without it, the duplicate name corrupts the set.\n\n**Add a new value to an existing dimension** (e.g. State=Hover):\n```\ncomponents(method:"clone", id:"<variant_id>", name:"Style=Primary, State=Hover", parentId:"<set_id>")\n```\nClone one variant per combination. For a Style\xD7State set, adding State=Hover requires two clones (one per Style). Use batch `items` for efficiency:\n```\ncomponents(method:"clone", items:[\n {id:"<Primary/Default>", name:"Style=Primary, State=Hover", parentId:"<set_id>"},\n {id:"<Secondary/Default>", name:"Style=Secondary, State=Hover", parentId:"<set_id>"}\n])\n```\nThen patch the new variants: `frames(method:"update", items:[{id:"<new>", fillVariableName:"color/hover"}])`\n\n**Add a new dimension** (e.g. Size=sm to a Style\xD7State set):\n1. Batch rename existing variants to include the new dimension: `frames(method:"update", items:[{id:"<each>", name:"..., Size=md"}])`\n2. Batch clone all variants with the new value: `components(method:"clone", items:[{id:"<each>", name:"..., Size=sm", parentId:"<set_id>"}])`\n3. Batch patch the new variants: `frames(method:"update", items:[{id:"<each>", padding:8, minHeight:32}])`\n\nProperty bindings (TEXT, INSTANCE_SWAP) are preserved on cloned variants.\n\n## Slots\n\nSlots are placeholder containers inside components that instance users can fill with custom content.\n\n- Create at component root: `frames(method:"create", type:"slot", items:[{parentId:"<comp_id>", name:"Content"}])`\n- Create nested inside a frame within a component: `frames(method:"create", type:"slot", items:[{parentId:"<frame_id>", name:"Content"}])`\n- In instances, add content by using the slot\'s ID as `parentId` on any create/reparent call\n- Empty slots are normal \u2014 they don\'t trigger lint warnings\n\n## Checking\n\nRun `components(method:"audit", id)` \u2014 checks both lint rules and property bindings in one call.',
3014
3128
  "library-components": '# Working with Library Components\n\nLibrary components are read-only \u2014 they come from external team libraries and cannot be edited in the current file.\n\n## Reading\n\nWhen reading nodes, library instances appear as stubs with their overridable properties:\n```\n{name: "Header", type: "INSTANCE", componentProperties: {"Platform": "Desktop"}}\n```\n\nLibrary internals are hidden: no `componentId`, no variable names, no style names. You see resolved values (hex colors, numbers) instead.\n\n## Using\n\nPlace library instances via `instances(method:"create", items:[{componentId:"<id>"}])` when you have a local component ID. For library components, instances are already placed by the designer \u2014 interact via `instances(method:"update")` to set properties.\n\n## Customizing\n\nTo edit a library component, clone it into the local file first:\n\n```\ncomponents(method:"clone", id:"<instanceId>")\n```\n\nThis resolves the instance to its source component (or full component set) and creates a local copy with a new ID. Edit the local copy freely \u2014 it is independent of the library.\n\nDo not attempt to `components(method:"get")` or `components(method:"update")` a library component directly \u2014 these will error.\n\n## Overriding Instance Properties\n\nUse `instances(method:"update")` to change overridable properties on library instances:\n```\ninstances(method:"update", items:[{id:"<instanceId>", properties:{"Label":"New Text", "State":"Hover"}}])\n```\n\nProperty names are clean (no hash suffixes needed for update \u2014 the system resolves partial keys).',
3015
3129
  "responsive-designs": '# Responsive Sizing\n\n## Workflow: Top-Down Sizing\n\nBuild layouts from the outside in:\n\n1. **Set the container first.** Every container needs an explicit width \u2014 either `width` + `layoutSizingHorizontal:"FIXED"` for shells and bounded panels, or `layoutSizingHorizontal:"FILL"` inside an auto-layout parent. Set `layoutMode` (VERTICAL or HORIZONTAL) and spacing/padding.\n2. **Children fill the container.** Use `layoutSizingHorizontal:"FILL"` on children so they stretch to the available space. Use `layoutSizingVertical:"HUG"` so height follows content.\n3. **Only leaves use HUG on both axes.** Buttons, badges, icons \u2014 elements with short, predictable content that should shrink-wrap.\n\nThis ensures every level of the tree has a clear width constraint. Text wraps, FILL children stretch, and the layout adapts when the container resizes.\n\nAlways set BOTH axes explicitly on every node. Omitting sizing leads to unintended defaults.\n\n## FIXED / FILL / HUG\n\n- **FIXED** \u2014 explicit bounded widths: page shell, sidebar, modal max-width, specimen frames\n- **FILL** \u2014 children that adapt to parent: cards, rows, panels, nav stacks, text that should wrap. Use `minWidth`/`maxWidth` for responsive constraints.\n- **HUG** \u2014 content-sized leaves only: icons, badges, pills, button labels\n\n## Anti-patterns: HUG/HUG\n\nHUG on both axes is the most common cause of broken layouts. It means "shrink to fit my content on both axes" \u2014 the container has no opinion about its own size and collapses to whatever its children measure.\n\n**Why HUG/HUG breaks designs:**\n\n1. **Text never wraps.** A HUG-width container grows to fit the longest text line. Body text becomes a single very long line instead of wrapping at a readable width. The design looks correct with short placeholder text but breaks with real content.\n\n2. **Layouts don\'t adapt.** HUG/HUG containers ignore their parent\'s width. A card inside a responsive column won\'t stretch to fill available space \u2014 it stays at its content width, leaving gaps or overflowing.\n\n3. **FILL children become under-constrained.** A child with `layoutSizingHorizontal:"FILL"` inside a HUG-width parent has no space to fill \u2014 the parent defers its width to its children, but the FILL child defers its width to the parent. The result is under-constrained sizing that produces unpredictable or collapsed layouts.\n\n4. **Cascading failures.** One HUG/HUG container at the top of a tree forces every child to resolve its own width. The entire layout becomes rigid and content-dependent instead of responsive.\n\n**HUG/HUG is only correct for:**\n- Buttons, pills, badges, chips \u2014 intrinsically-sized leaf elements with short, predictable content\n- Icon containers with fixed-size children\n- Inline tags and status indicators\n\n**For everything else, set at least one axis to FIXED or FILL:**\n- Cards, panels, list rows \u2192 `layoutSizingHorizontal:"FILL"`, vertical `HUG`. Add `minWidth`/`maxWidth` for responsive bounds.\n- Shells, sidebars, modals \u2192 `width` + `layoutSizingHorizontal:"FIXED"`, vertical `FILL` or `HUG`\n- Full-width sections \u2192 `layoutSizingHorizontal:"FILL"`, `layoutSizingVertical:"HUG"`\n\n## Wrapping Layouts (layoutWrap)\n\n`layoutWrap: WRAP` enables children to flow into new rows when they exceed the container width \u2014 like CSS `flex-wrap`. This only works with **HORIZONTAL** auto-layout. Figma does not support wrap on VERTICAL layouts.\n\n**When to use wrap:**\n- Card grids with a fixed number of columns at a known width\n- Tag/chip collections where items flow into multiple rows\n- Any layout where items should reflow based on available width\n\n**Horizontal wrap pattern:**\n```\nframes.create(type: "auto_layout", layoutMode: "HORIZONTAL", layoutWrap: "WRAP",\n itemSpacing: "space/16", counterAxisSpacing: "space/16")\n```\nChildren use FIXED width to control column count. `counterAxisSpacing` sets the gap between wrapped rows.\n\n**Vertical grid alternative:**\nSince VERTICAL layouts cannot wrap, build column-based grids by nesting VERTICAL columns inside a HORIZONTAL parent:\n```\nouter (HORIZONTAL, itemSpacing: 20, FILL width)\n col-1 (VERTICAL, FILL width, HUG height, itemSpacing: 20)\n col-2 (VERTICAL, FILL width, HUG height, itemSpacing: 20)\n col-3 (VERTICAL, FILL width, HUG height, itemSpacing: 20)\n```\nEach column gets equal width via FILL. Reparent items into columns for column-first ordering. This handles variable card heights per column independently.\n\n## Component Sizing\n\nComponent roots use `FILL` when placed in a parent \u2014 they adapt to context, not a fixed specimen width. Use `FIXED` only for the specimen (the component definition itself when it needs a specific preview width).\n\nExample sidebar item:\n- Instance: `FILL` in parent nav stack\n- Icon child: fixed 18x18\n- Label child: `FILL`\n- Badge child: `HUG`\n\n## Text Sizing\n\n- Body text inside containers: prefer `FILL` width, `HUG` height (auto-wraps)\n- Single-line labels: prefer `FILL` horizontal (truncates if needed)\n- Standalone headings: `HUG` is fine\n\nInside auto-layout parents, target `layoutSizingHorizontal:"FILL"` + `layoutSizingVertical:"HUG"` + `textAutoResize:"HEIGHT"` for text that should wrap. These are not auto-applied \u2014 set them explicitly on text.create or text.update.\n\n## Checklist\n\nBefore finalizing a layout, verify:\n1. No container with text has HUG on the horizontal axis (unless it\'s a button/badge)\n2. Children use FILL on the axis that should absorb available space \u2014 not blindly on both axes. Compact controls in horizontal rows often stay HUG vertically.\n3. Top-level containers have an explicit width (FIXED) or stretch to their parent (FILL)\n4. Run `lint(method:"check", nodeId:"<rootId>", rules:["composition"])` to catch overflow-parent, unbounded-hug, and fixed-in-autolayout issues',
3016
3130
  "token-discipline": '# Token Discipline\n\nEvery color, spacing value, and text style should come from a design token \u2014 not hardcoded values.\n\n## Colors\n\nBind fills and strokes to color variables instead of hex values.\n\n- Fill: `fillVariableName:"bg/primary"` or `fillStyleName:"Surface/Primary"`\n- Stroke: `strokeVariableName:"border/default"`\n- Text color: `fontColorVariableName:"text/primary"`\n\nIf no matching variable exists, create one first:\n```\nvariables(method:"create", collectionId:"Colors", items:[{name:"bg/accent", type:"COLOR", valuesByMode:{"Light":"#E8F0FE","Dark":"#1A3A5C"}, scopes:["ALL_FILLS"]}])\n```\n\n## Spacing and Radius\n\nPass a variable name string instead of a number for cornerRadius, padding, itemSpacing, strokeWeight, opacity.\n\n- `cornerRadius:"radius/8"` not `cornerRadius:8`\n- `paddingTop:"space/16"` not `paddingTop:16`\n- `itemSpacing:"space/8"` not `itemSpacing:8`\n\nCreate FLOAT variables with appropriate scopes:\n```\nvariables(method:"create", collectionId:"Metrics", items:[{name:"space/12", type:"FLOAT", value:12, scopes:["GAP","WIDTH_HEIGHT"]}])\n```\n\n## Text Styles\n\nApply text styles by name \u2014 don\'t set fontSize/fontFamily/fontWeight manually.\n\n- `textStyleName:"Body/M"` on text.create or frames.update\n- Create styles with `styles(method:"create", type:"text", items:[{name:"Body/M", fontFamily:"Inter", fontSize:14, lineHeight:{value:20, unit:"PIXELS"}}])`\n\n## Common Scopes\n\nCOLOR variables:\n- `ALL_FILLS` \u2014 background fills\n- `TEXT_FILL` \u2014 text color\n- `STROKE_COLOR` \u2014 borders and outlines\n\nFLOAT variables:\n- `GAP`, `WIDTH_HEIGHT` \u2014 spacing and padding\n- `CORNER_RADIUS` \u2014 border radius\n- `STROKE_FLOAT` \u2014 stroke weight\n- `OPACITY` \u2014 transparency\n\n## Checking\n\nLint rules `hardcoded-color`, `hardcoded-token`, `no-text-style` catch unbound values. Run `audit` on any node to check.',
@@ -35,6 +35,7 @@ __export(guards_exports, {
35
35
  framesCreateLine: () => framesCreateLine,
36
36
  framesCreateRectangle: () => framesCreateRectangle,
37
37
  framesCreateSection: () => framesCreateSection,
38
+ framesCreateSlot: () => framesCreateSlot,
38
39
  framesCreateSvg: () => framesCreateSvg,
39
40
  instancesCreate: () => instancesCreate,
40
41
  instancesDetach: () => instancesDetach,
@@ -499,6 +500,63 @@ var framesCreateSvg = /* @__PURE__ */ new Set([
499
500
  "x",
500
501
  "y"
501
502
  ]);
503
+ var framesCreateSlot = /* @__PURE__ */ new Set([
504
+ "annotations",
505
+ "blendMode",
506
+ "bottomLeftRadius",
507
+ "bottomRightRadius",
508
+ "componentId",
509
+ "cornerRadius",
510
+ "counterAxisAlignItems",
511
+ "counterAxisSpacing",
512
+ "effectStyleName",
513
+ "fillColor",
514
+ "fillStyleName",
515
+ "fillVariableName",
516
+ "fills",
517
+ "height",
518
+ "imageScaleMode",
519
+ "imageUrl",
520
+ "itemSpacing",
521
+ "layoutMode",
522
+ "layoutPositioning",
523
+ "layoutSizingHorizontal",
524
+ "layoutSizingVertical",
525
+ "layoutWrap",
526
+ "locked",
527
+ "maxHeight",
528
+ "maxWidth",
529
+ "minHeight",
530
+ "minWidth",
531
+ "name",
532
+ "opacity",
533
+ "overflowDirection",
534
+ "padding",
535
+ "paddingBottom",
536
+ "paddingLeft",
537
+ "paddingRight",
538
+ "paddingTop",
539
+ "parentId",
540
+ "primaryAxisAlignItems",
541
+ "rotation",
542
+ "strokeAlign",
543
+ "strokeBottomWeight",
544
+ "strokeColor",
545
+ "strokeLeftWeight",
546
+ "strokeRightWeight",
547
+ "strokeStyleName",
548
+ "strokeTopWeight",
549
+ "strokeVariableName",
550
+ "strokeWeight",
551
+ "strokes",
552
+ "strokesIncludedInLayout",
553
+ "topLeftRadius",
554
+ "topRightRadius",
555
+ "visible",
556
+ "width",
557
+ "x",
558
+ "y"
559
+ ]);
502
560
  var instancesCreate = /* @__PURE__ */ new Set([
503
561
  "blendMode",
504
562
  "componentId",
@@ -853,6 +911,7 @@ var mixinVectorStyleParams = /* @__PURE__ */ new Set(["fillStyleName", "fillVari
853
911
  framesCreateLine,
854
912
  framesCreateRectangle,
855
913
  framesCreateSection,
914
+ framesCreateSlot,
856
915
  framesCreateSvg,
857
916
  instancesCreate,
858
917
  instancesDetach,
@@ -40,6 +40,8 @@ declare const framesCreateGroup: ReadonlySet<string>;
40
40
  declare const framesCreateBooleanOperation: ReadonlySet<string>;
41
41
  /** frames create type="svg" */
42
42
  declare const framesCreateSvg: ReadonlySet<string>;
43
+ /** frames create type="slot" */
44
+ declare const framesCreateSlot: ReadonlySet<string>;
43
45
  /** instances.create item params */
44
46
  declare const instancesCreate: ReadonlySet<string>;
45
47
  /** instances.update item params */
@@ -111,4 +113,4 @@ declare const mixinTextParams: ReadonlySet<string>;
111
113
  /** vector_style_params */
112
114
  declare const mixinVectorStyleParams: ReadonlySet<string>;
113
115
 
114
- export { annotationsAdd, annotationsGet, annotationsRemove, annotationsSet, componentsCreateComponent, componentsCreateFromNode, componentsCreateVariantSet, componentsUpdate, framesCreateAutoLayout, framesCreateBooleanOperation, framesCreateEllipse, framesCreateFrame, framesCreateGroup, framesCreateLine, framesCreateRectangle, framesCreateSection, framesCreateSvg, instancesCreate, instancesDetach, instancesResetOverrides, instancesSwap, instancesUpdate, lintFix, mixinAutoLayoutParams, mixinBlendParams, mixinCornerParams, mixinFillParams, mixinFrameParams, mixinGeometryParams, mixinSceneParams, mixinSizingParams, mixinStrokeParams, mixinTextParams, mixinVectorStyleParams, nodeClone, nodeDelete, nodeReparent, nodeUpdate, prototypingAdd, stylesCreateEffect, stylesCreateGrid, stylesCreatePaint, stylesCreateText, stylesDelete, stylesUpdate, textCreate, textSetContent, variableCollectionsAddMode, variableCollectionsCreate, variableCollectionsDelete, variableCollectionsRemoveMode, variableCollectionsRenameMode, variableCollectionsUpdate, variablesCreate, variablesDelete, variablesUpdate };
116
+ export { annotationsAdd, annotationsGet, annotationsRemove, annotationsSet, componentsCreateComponent, componentsCreateFromNode, componentsCreateVariantSet, componentsUpdate, framesCreateAutoLayout, framesCreateBooleanOperation, framesCreateEllipse, framesCreateFrame, framesCreateGroup, framesCreateLine, framesCreateRectangle, framesCreateSection, framesCreateSlot, framesCreateSvg, instancesCreate, instancesDetach, instancesResetOverrides, instancesSwap, instancesUpdate, lintFix, mixinAutoLayoutParams, mixinBlendParams, mixinCornerParams, mixinFillParams, mixinFrameParams, mixinGeometryParams, mixinSceneParams, mixinSizingParams, mixinStrokeParams, mixinTextParams, mixinVectorStyleParams, nodeClone, nodeDelete, nodeReparent, nodeUpdate, prototypingAdd, stylesCreateEffect, stylesCreateGrid, stylesCreatePaint, stylesCreateText, stylesDelete, stylesUpdate, textCreate, textSetContent, variableCollectionsAddMode, variableCollectionsCreate, variableCollectionsDelete, variableCollectionsRemoveMode, variableCollectionsRenameMode, variableCollectionsUpdate, variablesCreate, variablesDelete, variablesUpdate };
@@ -40,6 +40,8 @@ declare const framesCreateGroup: ReadonlySet<string>;
40
40
  declare const framesCreateBooleanOperation: ReadonlySet<string>;
41
41
  /** frames create type="svg" */
42
42
  declare const framesCreateSvg: ReadonlySet<string>;
43
+ /** frames create type="slot" */
44
+ declare const framesCreateSlot: ReadonlySet<string>;
43
45
  /** instances.create item params */
44
46
  declare const instancesCreate: ReadonlySet<string>;
45
47
  /** instances.update item params */
@@ -111,4 +113,4 @@ declare const mixinTextParams: ReadonlySet<string>;
111
113
  /** vector_style_params */
112
114
  declare const mixinVectorStyleParams: ReadonlySet<string>;
113
115
 
114
- export { annotationsAdd, annotationsGet, annotationsRemove, annotationsSet, componentsCreateComponent, componentsCreateFromNode, componentsCreateVariantSet, componentsUpdate, framesCreateAutoLayout, framesCreateBooleanOperation, framesCreateEllipse, framesCreateFrame, framesCreateGroup, framesCreateLine, framesCreateRectangle, framesCreateSection, framesCreateSvg, instancesCreate, instancesDetach, instancesResetOverrides, instancesSwap, instancesUpdate, lintFix, mixinAutoLayoutParams, mixinBlendParams, mixinCornerParams, mixinFillParams, mixinFrameParams, mixinGeometryParams, mixinSceneParams, mixinSizingParams, mixinStrokeParams, mixinTextParams, mixinVectorStyleParams, nodeClone, nodeDelete, nodeReparent, nodeUpdate, prototypingAdd, stylesCreateEffect, stylesCreateGrid, stylesCreatePaint, stylesCreateText, stylesDelete, stylesUpdate, textCreate, textSetContent, variableCollectionsAddMode, variableCollectionsCreate, variableCollectionsDelete, variableCollectionsRemoveMode, variableCollectionsRenameMode, variableCollectionsUpdate, variablesCreate, variablesDelete, variablesUpdate };
116
+ export { annotationsAdd, annotationsGet, annotationsRemove, annotationsSet, componentsCreateComponent, componentsCreateFromNode, componentsCreateVariantSet, componentsUpdate, framesCreateAutoLayout, framesCreateBooleanOperation, framesCreateEllipse, framesCreateFrame, framesCreateGroup, framesCreateLine, framesCreateRectangle, framesCreateSection, framesCreateSlot, framesCreateSvg, instancesCreate, instancesDetach, instancesResetOverrides, instancesSwap, instancesUpdate, lintFix, mixinAutoLayoutParams, mixinBlendParams, mixinCornerParams, mixinFillParams, mixinFrameParams, mixinGeometryParams, mixinSceneParams, mixinSizingParams, mixinStrokeParams, mixinTextParams, mixinVectorStyleParams, nodeClone, nodeDelete, nodeReparent, nodeUpdate, prototypingAdd, stylesCreateEffect, stylesCreateGrid, stylesCreatePaint, stylesCreateText, stylesDelete, stylesUpdate, textCreate, textSetContent, variableCollectionsAddMode, variableCollectionsCreate, variableCollectionsDelete, variableCollectionsRemoveMode, variableCollectionsRenameMode, variableCollectionsUpdate, variablesCreate, variablesDelete, variablesUpdate };
@@ -421,6 +421,63 @@ var framesCreateSvg = /* @__PURE__ */ new Set([
421
421
  "x",
422
422
  "y"
423
423
  ]);
424
+ var framesCreateSlot = /* @__PURE__ */ new Set([
425
+ "annotations",
426
+ "blendMode",
427
+ "bottomLeftRadius",
428
+ "bottomRightRadius",
429
+ "componentId",
430
+ "cornerRadius",
431
+ "counterAxisAlignItems",
432
+ "counterAxisSpacing",
433
+ "effectStyleName",
434
+ "fillColor",
435
+ "fillStyleName",
436
+ "fillVariableName",
437
+ "fills",
438
+ "height",
439
+ "imageScaleMode",
440
+ "imageUrl",
441
+ "itemSpacing",
442
+ "layoutMode",
443
+ "layoutPositioning",
444
+ "layoutSizingHorizontal",
445
+ "layoutSizingVertical",
446
+ "layoutWrap",
447
+ "locked",
448
+ "maxHeight",
449
+ "maxWidth",
450
+ "minHeight",
451
+ "minWidth",
452
+ "name",
453
+ "opacity",
454
+ "overflowDirection",
455
+ "padding",
456
+ "paddingBottom",
457
+ "paddingLeft",
458
+ "paddingRight",
459
+ "paddingTop",
460
+ "parentId",
461
+ "primaryAxisAlignItems",
462
+ "rotation",
463
+ "strokeAlign",
464
+ "strokeBottomWeight",
465
+ "strokeColor",
466
+ "strokeLeftWeight",
467
+ "strokeRightWeight",
468
+ "strokeStyleName",
469
+ "strokeTopWeight",
470
+ "strokeVariableName",
471
+ "strokeWeight",
472
+ "strokes",
473
+ "strokesIncludedInLayout",
474
+ "topLeftRadius",
475
+ "topRightRadius",
476
+ "visible",
477
+ "width",
478
+ "x",
479
+ "y"
480
+ ]);
424
481
  var instancesCreate = /* @__PURE__ */ new Set([
425
482
  "blendMode",
426
483
  "componentId",
@@ -774,6 +831,7 @@ export {
774
831
  framesCreateLine,
775
832
  framesCreateRectangle,
776
833
  framesCreateSection,
834
+ framesCreateSlot,
777
835
  framesCreateSvg,
778
836
  instancesCreate,
779
837
  instancesDetach,
@@ -399,7 +399,7 @@ Create frame-like containers
399
399
 
400
400
  Example: frames(method:"create", type:"auto_layout", layoutMode:"VERTICAL", itemSpacing:16, padding:24)
401
401
 
402
- Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line | group | boolean_operation | svg)
402
+ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line | group | boolean_operation | svg | slot)
403
403
 
404
404
  ## frame \u2014 General-purpose frame \u2014 shrinks to content by default, static when width+height given
405
405
  name (string, optional) \u2014 Node name
@@ -618,7 +618,64 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
618
618
  name (string, optional) \u2014 Layer name (default: 'SVG')
619
619
  parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
620
620
  x (number, optional) \u2014 X position (default: 0)
621
- y (number, optional) \u2014 Y position (default: 0)`,
621
+ y (number, optional) \u2014 Y position (default: 0)
622
+
623
+ ## slot \u2014 Create a slot inside a component. Slots are placeholder containers that instance users fill with content. Defaults to VERTICAL auto-layout with FILL/HUG sizing \u2014 ready to receive children. Accepts all frame layout properties.
624
+ name (string, optional) \u2014 Node name
625
+ parentId (string, optional) \u2014 Parent node ID inside the owning component. Required unless componentId is provided.
626
+ x (number, optional) \u2014 X position (default: 0)
627
+ y (number, optional) \u2014 Y position (default: 0)
628
+ width (number, optional) \u2014 Width in px (omit to shrink-to-content via HUG)
629
+ height (number, optional) \u2014 Height in px (omit to shrink-to-content via HUG)
630
+ rotation (number, optional) \u2014 Rotation in degrees (0-360)
631
+ visible (boolean, optional) \u2014 Show/hide (default true)
632
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
633
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
634
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
635
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
636
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
637
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
638
+ fillStyleName (string, optional) \u2014 Paint style name for fill
639
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
640
+ imageUrl (string, optional) \u2014 Image source \u2014 'pexel:<id>' for Pexels photos, a public URL, or a local file path. SVGs are inserted as vectors; raster images become IMAGE fills.
641
+ imageScaleMode (FILL | FIT | CROP | TILE, optional) \u2014 How the image is scaled within the frame (default: FILL)
642
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
643
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
644
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
645
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
646
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
647
+ strokeTopWeight (string, optional)
648
+ strokeBottomWeight (string, optional)
649
+ strokeLeftWeight (string, optional)
650
+ strokeRightWeight (string, optional)
651
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
652
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
653
+ topLeftRadius (string, optional)
654
+ topRightRadius (string, optional)
655
+ bottomRightRadius (string, optional)
656
+ bottomLeftRadius (string, optional)
657
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)
658
+ layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
659
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
660
+ paddingTop (string, optional)
661
+ paddingRight (string, optional)
662
+ paddingBottom (string, optional)
663
+ paddingLeft (string, optional)
664
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
665
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
666
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
667
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
668
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
669
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
670
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
671
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
672
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
673
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
674
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
675
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
676
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
677
+ annotations (array, optional) \u2014 Set annotations \u2014 [{label?, labelMarkdown?, properties?, categoryId?}]. Properties validated per node type.
678
+ componentId (string, optional) \u2014 Owning component ID. Optional \u2014 auto-resolved from parentId by walking up ancestors.`,
622
679
  "commit": '# frames.commit\nCommit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n\nExample: frames(method:"commit", id:"1:234")\n\nParams:\n id (string, required) \u2014 Staged node ID to commit',
623
680
  "export": "# frames.export\nExport a node as PNG, JPG, SVG, SVG_STRING, or PDF\n\nParams:\n id (string, required) \u2014 Node ID to export\n format (PNG | JPG | SVG | SVG_STRING | PDF, optional) \u2014 Export format (default: PNG). SVG_STRING returns raw SVG text.\n scale (number, optional) \u2014 Export scale (default: 1, only for PNG/JPG)"
624
681
  }
@@ -901,7 +958,7 @@ Methods:
901
958
  // "fixed-in-autolayout" \u2014 FIXED-size children in auto-layout parents [heuristic]
902
959
  // "unbounded-hug" \u2014 HUG on both axes [unsafe; short leaf text\u2192style]
903
960
  // "hug-cross-axis" \u2014 HUG on cross-axis of constrained parent [heuristic; leaf nodes\u2192style]
904
- // "empty-container" \u2014 empty frames [style]
961
+ // "empty-container" \u2014 empty frames, excludes SLOT nodes [style]
905
962
  // Token rules [token]:
906
963
  // "hardcoded-color" \u2014 colors not using styles or variables [heuristic]
907
964
  // "hardcoded-token" \u2014 numeric values not bound to FLOAT variable [heuristic]
@@ -376,7 +376,7 @@ Create frame-like containers
376
376
 
377
377
  Example: frames(method:"create", type:"auto_layout", layoutMode:"VERTICAL", itemSpacing:16, padding:24)
378
378
 
379
- Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line | group | boolean_operation | svg)
379
+ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line | group | boolean_operation | svg | slot)
380
380
 
381
381
  ## frame \u2014 General-purpose frame \u2014 shrinks to content by default, static when width+height given
382
382
  name (string, optional) \u2014 Node name
@@ -595,7 +595,64 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
595
595
  name (string, optional) \u2014 Layer name (default: 'SVG')
596
596
  parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
597
597
  x (number, optional) \u2014 X position (default: 0)
598
- y (number, optional) \u2014 Y position (default: 0)`,
598
+ y (number, optional) \u2014 Y position (default: 0)
599
+
600
+ ## slot \u2014 Create a slot inside a component. Slots are placeholder containers that instance users fill with content. Defaults to VERTICAL auto-layout with FILL/HUG sizing \u2014 ready to receive children. Accepts all frame layout properties.
601
+ name (string, optional) \u2014 Node name
602
+ parentId (string, optional) \u2014 Parent node ID inside the owning component. Required unless componentId is provided.
603
+ x (number, optional) \u2014 X position (default: 0)
604
+ y (number, optional) \u2014 Y position (default: 0)
605
+ width (number, optional) \u2014 Width in px (omit to shrink-to-content via HUG)
606
+ height (number, optional) \u2014 Height in px (omit to shrink-to-content via HUG)
607
+ rotation (number, optional) \u2014 Rotation in degrees (0-360)
608
+ visible (boolean, optional) \u2014 Show/hide (default true)
609
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
610
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
611
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
612
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
613
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
614
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
615
+ fillStyleName (string, optional) \u2014 Paint style name for fill
616
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
617
+ imageUrl (string, optional) \u2014 Image source \u2014 'pexel:<id>' for Pexels photos, a public URL, or a local file path. SVGs are inserted as vectors; raster images become IMAGE fills.
618
+ imageScaleMode (FILL | FIT | CROP | TILE, optional) \u2014 How the image is scaled within the frame (default: FILL)
619
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
620
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
621
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
622
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
623
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
624
+ strokeTopWeight (string, optional)
625
+ strokeBottomWeight (string, optional)
626
+ strokeLeftWeight (string, optional)
627
+ strokeRightWeight (string, optional)
628
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
629
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
630
+ topLeftRadius (string, optional)
631
+ topRightRadius (string, optional)
632
+ bottomRightRadius (string, optional)
633
+ bottomLeftRadius (string, optional)
634
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)
635
+ layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
636
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
637
+ paddingTop (string, optional)
638
+ paddingRight (string, optional)
639
+ paddingBottom (string, optional)
640
+ paddingLeft (string, optional)
641
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
642
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
643
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
644
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
645
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
646
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
647
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
648
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
649
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
650
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
651
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
652
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
653
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
654
+ annotations (array, optional) \u2014 Set annotations \u2014 [{label?, labelMarkdown?, properties?, categoryId?}]. Properties validated per node type.
655
+ componentId (string, optional) \u2014 Owning component ID. Optional \u2014 auto-resolved from parentId by walking up ancestors.`,
599
656
  "commit": '# frames.commit\nCommit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n\nExample: frames(method:"commit", id:"1:234")\n\nParams:\n id (string, required) \u2014 Staged node ID to commit',
600
657
  "export": "# frames.export\nExport a node as PNG, JPG, SVG, SVG_STRING, or PDF\n\nParams:\n id (string, required) \u2014 Node ID to export\n format (PNG | JPG | SVG | SVG_STRING | PDF, optional) \u2014 Export format (default: PNG). SVG_STRING returns raw SVG text.\n scale (number, optional) \u2014 Export scale (default: 1, only for PNG/JPG)"
601
658
  }
@@ -878,7 +935,7 @@ Methods:
878
935
  // "fixed-in-autolayout" \u2014 FIXED-size children in auto-layout parents [heuristic]
879
936
  // "unbounded-hug" \u2014 HUG on both axes [unsafe; short leaf text\u2192style]
880
937
  // "hug-cross-axis" \u2014 HUG on cross-axis of constrained parent [heuristic; leaf nodes\u2192style]
881
- // "empty-container" \u2014 empty frames [style]
938
+ // "empty-container" \u2014 empty frames, excludes SLOT nodes [style]
882
939
  // Token rules [token]:
883
940
  // "hardcoded-color" \u2014 colors not using styles or variables [heuristic]
884
941
  // "hardcoded-token" \u2014 numeric values not bound to FLOAT variable [heuristic]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ufira/vibma",
3
3
  "description": "Vibma — Vibe Design meets Figma. AI-powered MCP bridge for designing in Figma.",
4
- "version": "1.1.3-rc1",
4
+ "version": "1.1.3-rc2",
5
5
  "license": "MIT",
6
6
  "author": "ufira <https://github.com/ufira-ai>",
7
7
  "homepage": "https://github.com/ufira-ai/vibma",