@snackbit/opendil 0.0.0 → 0.2.0

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.
Files changed (130) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +137 -2
  3. package/THIRD_PARTY_NOTICES.md +9 -0
  4. package/bin/opendil.mjs +75 -0
  5. package/bin/publish-directory.d.mts +18 -0
  6. package/bin/publish-directory.mjs +188 -0
  7. package/dist/agent-spec.js +9 -0
  8. package/dist/chunk-RPZW4WVX.js +2 -0
  9. package/dist/chunk-ZSTXLIS6.js +2 -0
  10. package/dist/index.js +2 -0
  11. package/dist/mermaid-diagram-GFWD4Y2X.js +2 -0
  12. package/dist/runtime/frame.html +2435 -0
  13. package/dist/runtime/frame.js +4621 -0
  14. package/dist/spec/genui.agent.full.md +1927 -0
  15. package/dist/spec/genui.agent.md +479 -0
  16. package/dist/spec/genui.examples.md +836 -0
  17. package/dist/styled-renderer-PHI4MNPF.js +2441 -0
  18. package/dist/styles.css +2434 -0
  19. package/dist/types/agent-spec.d.ts +12 -0
  20. package/dist/types/components/ui/controls/button.d.ts +10 -0
  21. package/dist/types/components/ui/controls/checkbox.d.ts +4 -0
  22. package/dist/types/components/ui/controls/input.d.ts +3 -0
  23. package/dist/types/components/ui/controls/radio-group.d.ts +5 -0
  24. package/dist/types/components/ui/controls/select.d.ts +14 -0
  25. package/dist/types/components/ui/controls/slider.d.ts +4 -0
  26. package/dist/types/components/ui/controls/tabs.d.ts +7 -0
  27. package/dist/types/components/ui/controls/textarea.d.ts +3 -0
  28. package/dist/types/components/ui/controls/toggle-group.d.ts +10 -0
  29. package/dist/types/components/ui/controls/toggle.d.ts +9 -0
  30. package/dist/types/components/ui/display/badge.d.ts +9 -0
  31. package/dist/types/components/ui/display/card.d.ts +9 -0
  32. package/dist/types/components/ui/display/chart.d.ts +39 -0
  33. package/dist/types/components/ui/display/separator.d.ts +4 -0
  34. package/dist/types/components/ui/display/skeleton.d.ts +2 -0
  35. package/dist/types/components/ui/display/table.d.ts +10 -0
  36. package/dist/types/components/ui/media/carousel.d.ts +19 -0
  37. package/dist/types/components/ui/overlays/collapsible.d.ts +6 -0
  38. package/dist/types/components/ui/overlays/popover.d.ts +11 -0
  39. package/dist/types/components/ui/overlays/tooltip.d.ts +8 -0
  40. package/dist/types/components/ui/overlays/ui-scope.d.ts +27 -0
  41. package/dist/types/dil/custom-component.d.ts +14 -0
  42. package/dist/types/dil/customization.d.ts +21 -0
  43. package/dist/types/dil/dil-renderer.d.ts +90 -0
  44. package/dist/types/dil/isolation/frame-startup.d.ts +18 -0
  45. package/dist/types/dil/isolation/frame-theme.d.ts +14 -0
  46. package/dist/types/dil/isolation/frame-viewport.d.ts +30 -0
  47. package/dist/types/dil/isolation/frame.d.ts +1 -0
  48. package/dist/types/dil/isolation/isolated-renderer.d.ts +28 -0
  49. package/dist/types/dil/isolation/overlay-room.d.ts +29 -0
  50. package/dist/types/dil/isolation/shadow-renderer.d.ts +7 -0
  51. package/dist/types/dil/isolation/shadow-styles.d.ts +2 -0
  52. package/dist/types/dil/isolation/viewport-scroll.d.ts +7 -0
  53. package/dist/types/dil/isolation/vm-worker.d.ts +1 -0
  54. package/dist/types/dil/message-renderer.d.ts +17 -0
  55. package/dist/types/dil/parser/dil-parser.d.ts +74 -0
  56. package/dist/types/dil/parser/lexical.d.ts +27 -0
  57. package/dist/types/dil/parser/literal-tag.d.ts +16 -0
  58. package/dist/types/dil/parser/markdown-lexing.d.ts +41 -0
  59. package/dist/types/dil/parser/stream-worker.d.ts +1 -0
  60. package/dist/types/dil/parser/types.d.ts +53 -0
  61. package/dist/types/dil/parser/unfinished.d.ts +22 -0
  62. package/dist/types/dil/parser/vocabulary.d.ts +12 -0
  63. package/dist/types/dil/render-error.d.ts +47 -0
  64. package/dist/types/dil/renderer-environment.d.ts +33 -0
  65. package/dist/types/dil/renderer-handle.d.ts +4 -0
  66. package/dist/types/dil/runtime/action-receipt.d.ts +5 -0
  67. package/dist/types/dil/runtime/child-list.d.ts +8 -0
  68. package/dist/types/dil/runtime/document.d.ts +54 -0
  69. package/dist/types/dil/runtime/evaluation-cache.d.ts +24 -0
  70. package/dist/types/dil/runtime/execution-queue.d.ts +56 -0
  71. package/dist/types/dil/runtime/expressions.d.ts +62 -0
  72. package/dist/types/dil/runtime/inline-worker.d.ts +33 -0
  73. package/dist/types/dil/runtime/markdown-stream.d.ts +17 -0
  74. package/dist/types/dil/runtime/presentation-history.d.ts +14 -0
  75. package/dist/types/dil/runtime/presentation-scheduler.d.ts +16 -0
  76. package/dist/types/dil/runtime/render-budget.d.ts +10 -0
  77. package/dist/types/dil/runtime/view-cost.d.ts +10 -0
  78. package/dist/types/dil/styled-renderer.d.ts +39 -0
  79. package/dist/types/dil/view/conditional-view.d.ts +12 -0
  80. package/dist/types/dil/view/loading-block.d.ts +7 -0
  81. package/dist/types/dil/view/markdown-node.d.ts +12 -0
  82. package/dist/types/dil/view/node-children.d.ts +13 -0
  83. package/dist/types/dil/view/node-view.d.ts +11 -0
  84. package/dist/types/dil/view/progressive-reveal.d.ts +7 -0
  85. package/dist/types/dil/view/render-boundary.d.ts +35 -0
  86. package/dist/types/dil/view/render-limit.d.ts +14 -0
  87. package/dist/types/dil/view/repeated-nodes.d.ts +15 -0
  88. package/dist/types/dil/view/reveal/controller.d.ts +32 -0
  89. package/dist/types/dil/view/reveal/presentation.d.ts +13 -0
  90. package/dist/types/dil/view/reveal-options.d.ts +11 -0
  91. package/dist/types/dil/view/scroll/controller.d.ts +42 -0
  92. package/dist/types/dil/view/scroll/host-viewport.d.ts +24 -0
  93. package/dist/types/dil/view/scroll/root-tracker.d.ts +17 -0
  94. package/dist/types/dil/view/scroll/scroll-root.d.ts +36 -0
  95. package/dist/types/dil/view/scroll-options.d.ts +25 -0
  96. package/dist/types/dil/view/stream-follow.d.ts +15 -0
  97. package/dist/types/dil/view/table-context.d.ts +15 -0
  98. package/dist/types/dil/view/virtual-flow.d.ts +15 -0
  99. package/dist/types/dil/widgets/action-feedback.d.ts +11 -0
  100. package/dist/types/dil/widgets/async-image.d.ts +6 -0
  101. package/dist/types/dil/widgets/charts/chart-hover.d.ts +17 -0
  102. package/dist/types/dil/widgets/charts/chart-legend.d.ts +10 -0
  103. package/dist/types/dil/widgets/charts/chart-pie.d.ts +16 -0
  104. package/dist/types/dil/widgets/charts/chart-selection.d.ts +8 -0
  105. package/dist/types/dil/widgets/charts/chart-series.d.ts +19 -0
  106. package/dist/types/dil/widgets/charts/chart-snapping.d.ts +13 -0
  107. package/dist/types/dil/widgets/charts/dil-chart.d.ts +5 -0
  108. package/dist/types/dil/widgets/charts/snap-cursor.d.ts +12 -0
  109. package/dist/types/dil/widgets/charts/snap-tooltip.d.ts +12 -0
  110. package/dist/types/dil/widgets/code/code-editor.d.ts +9 -0
  111. package/dist/types/dil/widgets/code/highlighted-code.d.ts +25 -0
  112. package/dist/types/dil/widgets/code-block.d.ts +11 -0
  113. package/dist/types/dil/widgets/control-revision.d.ts +1 -0
  114. package/dist/types/dil/widgets/control-state.d.ts +8 -0
  115. package/dist/types/dil/widgets/controls.d.ts +25 -0
  116. package/dist/types/dil/widgets/graphs/graph-model.d.ts +13 -0
  117. package/dist/types/dil/widgets/graphs/node-graph.d.ts +6 -0
  118. package/dist/types/dil/widgets/graphs/service-node.d.ts +3 -0
  119. package/dist/types/dil/widgets/mermaid-diagram.d.ts +5 -0
  120. package/dist/types/dil/widgets/primitives/attribute-values.d.ts +12 -0
  121. package/dist/types/dil/widgets/primitives/primitive.d.ts +17 -0
  122. package/dist/types/dil/widgets/primitives/vocabulary.d.ts +5 -0
  123. package/dist/types/dil/widgets/use-control-value.d.ts +2 -0
  124. package/dist/types/index.d.ts +9 -0
  125. package/dist/types/lib/cn.d.ts +2 -0
  126. package/dist/types/ui.d.ts +11 -0
  127. package/dist/ui.js +2 -0
  128. package/package.json +85 -4
  129. package/styles/tailwind.css +443 -0
  130. package/styles/tokens.css +32 -0
@@ -0,0 +1,9 @@
1
+ // src/agent-spec.ts
2
+ var agentSpec = '# GenUI Agent Specification\n\n## 1. Output format and safety\n\nGenerate OpenDIL markup: Markdown, supported component tags, expressions, and\ndirectives. Mix prose and UI directly. Do not enclose the response in a code\nfence unless asked to show source. Match component and property names exactly.\nClose every tag and directive before finishing. Use self-closing tags for leaves.\n\nUse only the APIs below. Do not emit arbitrary HTML, React JSX, imports,\nTypeScript, CSS, spread attributes, DOM handlers, or injected HTML. Render supplied\nfacts faithfully; label invented example data. Do not imply that a label connects\na component to a service. Provide readable labels and visible validation messages.\nAvoid nested interactive controls. Keep calculations and output bounded.\n\nExpressions execute in an isolated QuickJS worker. Browser globals, DOM access,\nnetwork clients, storage, browser timers, Node APIs, and dynamic module loading\nare unavailable as authoring APIs. Do not use `eval` or `Function`; this is an\nauthoring rule, not a claim that QuickJS removes those JavaScript primitives.\nDo not probe VM internals or overwrite globals. Host operations require the\nexplicit API and invocation rules in section 6. Do not request weaker containment.\n\n## 2. Syntax and parsing\n\n### Markdown\n\nUse headings, paragraphs, lists, emphasis, blockquotes, fenced code, and GFM\ntables, strikethrough, and task lists. Markdown task lists are presentation, not\nstate-bound inputs. Links render their labels as inert text; Markdown images are\nsuppressed. Use a visible URL as text when the destination matters. No authored\nHTML link or image tag is supported. Mermaid fences render diagrams.\n\nKeep fences on separate lines with at most three leading spaces. Fences and\ninline code spans protect their contents from DIL parsing: braces, tags, and\ndirectives inside them display literally and never evaluate. A code span ends at\na blank line or at a line that starts a list item, heading, blockquote,\ncomponent tag, or block directive; an unmatched backtick protects nothing.\nLowercase HTML-like tags that are not DIL tags, such as `<div>` or `<br>`,\ndisplay as plain text; capitalized unknown tags are unsupported components. For\na literal brace in ordinary prose, use an expression such as `{"{"}`.\n\n### JavaScript expressions\n\nAttributes accept `name="literal"`, `name=\'literal\'`, `flag` (true), or\n`name={expression}`. Use braces for numbers, booleans, arrays, objects, and\ncallbacks. Unquoted scalar values, spread attributes, and JSX children inside\nJavaScript are unsupported. For a quote inside a string prop, use a JavaScript\nstring expression rather than escaped quoted-attribute syntax.\n\n`{expression}` interpolates text; it never parses returned strings as markup.\nStrings and numbers display directly; null/undefined display empty, booleans as\ntext, and objects/arrays as `[object Object]`. Select fields, join arrays, or\nformat explicitly. Expressions support JavaScript operators, property/computed\naccess, optional chaining, literals, template strings, functions, and array\nmethods. Use directives to create UI trees, not `.map()` returning JSX.\n\nDo not put statements in interpolation. Callback function bodies may contain\nbounded statements. Keep rendered expressions and derived bindings pure; perform\nstate changes only in callbacks. Use plain JSON-compatible data across bindings;\navoid cycles, class instances, BigInt, and non-finite numbers. Functions are\ncallback values, not data records. `Intl.NumberFormat` is a limited bridge that\nformats en-US numbers with zero maximum fractional digits; locale/options are\nnot a general formatting API. Use explicit string formatting for other needs.\n\n### State declarations\n\nDeclare one binding per `{@body ...}` directive, before UI:\n\n```dil\n{@body const [count,setCount] = DIL.useState(0)}\n{@body const doubled = count * 2}\n{@body const increment = () => setCount(previous => previous + 1)}\n<button onClick={increment}>Increment</button>\n<text>{doubled}</text>\n```\n\nSupported declaration forms: `const [name,setName] = DIL.useState(initial)` and\n`const name = expression`. An optional trailing semicolon is accepted. Use\nunique document-wide names beginning with a letter or underscore and containing\nletters, digits, or underscores. No `let`, `var`, function declarations, multiple\ndeclarations in one directive, arbitrary destructuring, or other hooks exist.\n\nState initializes once per document; a lazy initializer is supported. Ordinary\nconst bindings are getters evaluated on demand, not once-only snapshots. Keep\ninitializers and getters side-effect-free. Declarations are document-scoped even\nwhen their source appears inside a conditional or loop. Declare them\nunconditionally at the top level; they cannot capture iteration variables or\ncreate item-local state.\n\n### Conditional rendering\n\n```dil\n{@body const status = "ready"}\n{#if status === "ready"}\n <badge color="success">Ready</badge>\n{:else if status === "waiting"}\n <caption>Waiting</caption>\n{:else}\n <text>Unavailable</text>\n{/if}\n```\n\nUse JavaScript truthiness. The first matching branch renders. Else-if and else\nare optional; close the enclosing if. Directives can produce required named\nchildren without extra wrappers.\n\nRepeat arrays with `{#each items as item,index}...{/each}`; index is optional\nand zero-based. Non-arrays render no items; generate arrays deliberately. Give\nrepeated records stable unique string or number `id` values. Without such IDs,\nidentity falls back to position. There is no JSX `key` or keyed-each syntax.\nNested each scopes can read outer variables; declarations still cannot.\n\n```dil\n{@body const items = [{id:"a",label:"Alpha"},{id:"b",label:"Beta"}]}\n{#each items as item,index}\n <text>{index + 1}. {item.label}</text>\n{/each}\n```\n\nStream append-only source: keep the full previous prefix and append suffixes.\nIncomplete tags, attributes, and directives wait for more input; complete them\nbefore ending. Close useful children early. A repeated template waits for\n`{/each}` before rendering. Streaming does not authorize actions. State survives\nappends and virtualized unmounts within the document; a fresh document resets it.\nDo not rewrite previous source to update state.\n\n## 3. Component API\n\nNotation: `?` = optional; `=value` = default. Unmarked props must be supplied for\nthe intended output; the parser does not enforce a complete prop schema.\n`callback` signatures are listed in section 6. Unknown props are not extensions.\n\nChildren categories:\n\n- `inline`: text, inline Markdown, and inline components, including icons.\n- `generic`: inline and block content.\n- `raw`: unparsed source, with no expressions or component children.\n- `none`: no children.\n- Named children: only the listed direct component types; whitespace is allowed.\n If/each directives may produce those children. `one` means exactly one.\n\nThese are generation contracts. The parser accepts a wider tree than valid UI\ncomposition. Never nest buttons, pressables, inputs, or choice controls inside\nanother action control. Do not put block content inside inline text.\n\nShared layout props (only entries marked `layout`):\n`padding?:number|{x?:number,y?:number}`, `gap?:number`,\n`radius?:"sm"|"md"|"lg"|"xl"|"2xl"|"full"|string`,\n`border?:boolean|{size?:number,color?:string}`, `background?:string`,\n`clip?:boolean`, `width?:number|string`, `maxWidth?:number|string`,\n`height?:number|string`, `flex?:number|string`, `columns?:number`,\n`align?:string`, `justify?:string`, `wrap?:"wrap"`.\n\nNumeric padding/gap use 4px units. Numeric width/maxWidth/height use pixels;\nstring dimensions use valid CSS lengths or percentages. Flex numbers are flex\nvalues, not pixel dimensions. Named radii are 4/6/8/12/16px and full rounding.\nBorder defaults to 1px in the theme border color when enabled. Unspecified layout\nprops retain component styling. Prefer positive integer columns; grids reduce\ncolumns responsively. `columns` has no useful grid effect on a row.\n\nPrefer `align="start"|"center"|"end"|"stretch"` and\n`justify="start"|"center"|"end"|"between"`. Use `wrap="wrap"` for wrapping rows.\nUse `spacer` to consume remaining row space. Clipping may hide content; avoid it\naround controls and long text unless deliberate.\n\nColor values: `default`, `primary`, `secondary`, `tertiary`, `success`, `warning`,\n`danger`, `surface-secondary`, `surface-tertiary`, `subtle`, `strong`, or a valid\nCSS color shorter than 128 characters. Do not supply `url`, custom `var()`, CSS\ndeclarations, or style objects as color values. Use semantic colors and readable\ntext; color alone must not communicate status.\n\n### Text components\n\n- <text>: color?:string, size?:"xs"|"sm"|"md"|"lg"|"xl"|"2xl", weight?:"medium", tabularNums?:boolean; children: inline\n- <title>: color?:string, size?:"xs"|"sm"|"md"|"lg"|"xl"|"2xl", weight?:"medium", tabularNums?:boolean; children: inline\n- <caption>: color?:string, size?:"xs"|"sm"|"md"|"lg"|"xl"|"2xl", weight?:"medium", tabularNums?:boolean; children: inline\n- <badge>: color?:string; children: inline\n- <label>: no props; children: inline\n- <CodeBlock>: language?:string="", editable?:boolean=false; children: raw\n\nText sizes xs/sm/md/lg/xl/2xl are 12/14/16/18/24/30px at the normal root size.\nTitle renders h3, defaults to 18px/600, and ignores weight overrides. Caption\ndefaults to secondary color and 12px. Use Markdown headings for document\nhierarchy. `weight="medium"` means 500 on text/caption; use Markdown emphasis\nfor bold. `label` is visual text, not an input association; name inputs explicitly.\n\nCodeBlock reads literal children until the exact `</CodeBlock>` delimiter.\nNo `source`, `value`, or `onChange` prop exists. Editable code is a local draft,\nnever executed and not readable from DIL state. Its copy/wrap controls are built\nin. Avoid embedding its closing delimiter in its raw source; use fenced code\ninstead. Keep source below 131,072 characters and copyable content at 65,536 or\nfewer characters. Fenced code is another display option, not a runnable program.\n\n### Media components\n\n- <AsyncImage>: query:string; children: none\n\nAsyncImage renders an offline placeholder illustration. Query is its alt text;\nit is not an image URL, search request, or image-generation call. Provide a\ndescriptive query and do not claim the illustration depicts verified evidence.\nNo stock audio, video, file viewer, or external image-source prop exists.\n\n### Layout components\n\n- <box>: layout; children: generic\n- <row>: layout; children: generic\n- <grid>: layout; children: generic\n- <grid-item>: layout; children: generic\n- <spacer>: no props; children: none\n- <divider>: no props; children: none\n- <table>: no props; children: table-row\n- <table-row>: no props; children: table-cell\n- <table-cell>: layout; children: generic\n- <popover>: no props; children: popover-trigger | popover-content\n- <popover-trigger>: no props; children: one button\n- <popover-content>: side?:"top"|"bottom"="bottom", align?:"end"|"center"="center"; children: generic\n- <carousel>: no props; children: carousel-item\n- <carousel-item>: no props; children: generic\n\nUse box for vertical content, row for horizontal groups, grid for responsive\ncolumns, and grid-item for a grid child. Grid-item has no span/placement API.\nTable supplies its own body; no table-section, header, colSpan, or rowSpan exists.\nUse a first row of clear labels or a Markdown table when headers matter.\n\nComposition contracts:\n\n```text\n<table>\n children: table-row\n <table-row>\n children: table-cell\n <table-cell>\n children: generic\n\n<popover>\n children: popover-trigger | popover-content\n <popover-trigger>\n children: one button\n <popover-content>\n children: generic\n\n<carousel>\n children: carousel-item\n <carousel-item>\n children: generic\n```\n\nUse one trigger and one content region per popover. The trigger button opens it\nwithout an authored handler; content may contain controls. Keep carousel items\ndirect children. Carousel navigation is built in; no authored active-index prop\nor navigation callback exists. Avoid carousels for required sequential form steps.\n\n### Input components\n\n- <button>: aria-label?:string, disabled?:boolean=false, variant?:"outline"|"ghost"|"default"="default", size?:"sm"|"xs"|"default"="default", block?:boolean=false, onClick?:callback; children: inline\n- <pressable>: layout, color?:string, onClick?:callback; children: generic\n- <input>: aria-label?:string, value?:string="", placeholder?:string="", disabled?:boolean=false, onChange?:callback; children: none\n- <slider>: aria-label?:string, min?:number=0, max?:number=100, step?:number=1, value?:number=0, marks?:{label:string}[], disabled?:boolean=false, onChange?:callback; children: none\n- <checkbox>: checked?:boolean=false, disabled?:boolean=false, lineThrough?:boolean=true, onChange?:callback; children: inline\n- <radio-group>: aria-label?:string, value?:string="", direction?:"row", onChange?:callback; children: radio\n- <radio>: value:string; children: inline\n- <segmented-control>: aria-label?:string, value?:string="", options:{value:string,label:string}[], onChange?:callback; children: none\n\nGive input, slider, radio-group, and segmented-control an explicit aria-label.\nCheckbox/radio children supply visible labels. Name icon-only buttons with\naria-label. Pressable\'s noninteractive content must name its action. Only the\ncomponents listing `disabled` accept authored disabled state.\n\nBind controlled values and callbacks to state. Keep slider min < max, step > 0,\nand value within range; marks are evenly distributed labels, not tick positions.\nUse unique nonempty strings for choice values; keep selection among options.\nRadio-group is vertical by default; direction="row" wraps horizontally.\n\n```text\n<radio-group>\n children: radio\n <radio>\n children: inline\n```\n\nNo defaultValue, loading, type, minLength, required, pattern, form, submit event,\nselect, textarea, or arbitrary DOM event prop exists. Validate using derived\nvalues, visible messages, disabled buttons, and a guard inside the handler.\n\n## 4. Specialized components\n\n### Data-linked components\n\nNo stock remote-data, query, subscription, or provider component exists. Pass\nsupplied arrays/records to Chart and NodeGraph content or render them with each.\nSee Visualizations for their exact data shapes and section 6 for binding rules.\nLabels such as "live" do not establish a connection or refresh behavior.\n\n### Links and citations\n\nNo link, citation, footnote lookup, source registry, or URL-opening action is\nexposed. Markdown link labels display without navigation. Preserve source titles\nand visible supplied URLs as text; do not invent reference IDs or destinations.\nA button cannot open a URL through an undocumented browser operation.\n\n### Embedded application blocks\n\nNo iframe, app block, script, embed, or independently running application is\nauthorable. CodeBlock displays source only. Custom components require an explicit\nhost-supplied contract specifying names, props, children, and actions; absent that\ncontract, use stock components. Do not infer custom capabilities from site demos.\n\n## 5. Visualizations\n\n### Images\n\nUse AsyncImage only with its documented placeholder semantics. Markdown images\ndo not display. For authored diagrams or illustrations, use presentation-only SVG:\n\n- <svg>: svg props; children: SVG elements\n\nSVG elements: svg, defs, marker, path, rect, circle, line, polyline, polygon, g,\nellipse, text, tspan, linearGradient, stop. Names are case-sensitive. SVG text is\nSVG content inside an SVG subtree, not the DIL text component.\n\nShared SVG props: viewBox, width, height, x, y, cx, cy, r, rx, ry, d, fill, stroke,\nstrokeWidth, fontSize, fontWeight, opacity, id, markerWidth, markerHeight, refX,\nrefY, orient, markerEnd. Use suitable number/string values. Give the root a\nviewBox and bounded dimensions. SVG has no layout-prop inheritance from DIL.\n\n```text\n<svg>\n children: SVG elements\n <defs>\n children: marker | linearGradient\n <marker>\n children: SVG shapes\n <linearGradient>\n children: stop\n <g>\n children: SVG shapes | g | text\n <text>\n children: text content | tspan\n```\n\nThese are useful SVG compositions, not a complete element-specific schema.\nUse only local references such as `url(#arrow)`. No href, external image, script,\nforeignObject, style, event handler, transform, points, offset, or stopColor prop\nis exposed. In particular, polyline/polygon and gradient elements have a limited\nattribute API; use path/rect/circle for reliable geometry. Do not invent missing\nSVG attributes. Give diagrams a nearby text description; no SVG aria-label prop\nis exposed. Never simulate interactive controls with SVG.\n\n### Charts\n\n- <Chart>: content:object; children: none\n- <NodeGraph>: content:object, selectedId?:string, onSelect?:callback; children: none\n- <Mermaid>: source:string; children: none\n\nChart content for line/bar/scatter:\n`{chartType:"line"|"bar"|"scatter",data:object[],xKey:string,\nseries:{dataKey:string,label?:string}[]}`.\nFor pie: `{chartType:"pie",data:object[],nameKey:string,valueKey:string}`.\nSupply chartType explicitly; omission currently falls back to line. Series keys\nmust identify numeric fields. Scatter xKey is numeric; line/bar may use category\nstrings. Keep values finite, units consistent, and keys/labels distinct. Pie\nvalues should be nonnegative and names unique. No axes, palette, size, tooltip,\nlegend, or callback customization props exist. Legend selection for multi-series\nline/bar charts is internal; it is not DIL state. Supply a nearby textual summary.\n\nNodeGraph content:\n`{nodes:{id:string,label:string,sub?:string,x?:number,y?:number}[],\nedges:{id?:string,source:string,target:string,label?:string}[]}`.\nUse unique node IDs and valid edge endpoints. Coordinates are optional hints;\nlayout adjusts them to avoid overlap. Maximum 200 nodes and 400 edges; excess\nentries are truncated and invalid endpoints filtered. Graph selection can bind\nselectedId/onSelect; dragging and connecting are unavailable. Pan/zoom controls\nare built in. No custom node types, styles, or edge handlers are authorable.\n\nMermaid accepts source text as a string, also through a fenced mermaid block.\nKeep it within 8,192 characters and 100 edges. Do not include configuration\ndirectives, frontmatter, authored CSS, HTML, click actions, or external links.\nOutput is sanitized. Mermaid is a diagram display, not an interaction surface.\n\n### Maps\n\nNo map, geocoding, tile, marker, or geographic layer API exists. Present supplied\nlocations as text/table data. Use a supplied URL as visible text; do not imply an\ninteractive map or fabricate geographic results.\n\n## 6. Interactivity\n\n### State management\n\nOnly `DIL.useState(initialValue)` exists. Pass a value or lazy initializer.\nSetters accept a replacement or `(previous) => nextValue`. Replace arrays and\nobjects; never mutate them in place. Use functional setters for repeated updates\nthat depend on the previous value. Derive totals/filtering with const getters.\nNo useEffect, useMemo, useCallback, useRef, useId, lifecycle, or async data hook\nis exposed. Do not perform work merely because a component renders.\n\nState belongs to the mounted document, not the server, browser storage, or a\nglobal app store. Keep state for repeated records in a top-level array/object\nkeyed by ID. Hiding a branch does not reset document state. Code editor drafts\nand chart legend state are internal widget state, not author-visible bindings.\n\n### Event callbacks\n\n| Component callback | Argument |\n| ------------------------------------------------ | ----------------------------------- |\n| button.onClick, pressable.onClick | none; ignore the undefined argument |\n| input.onChange | value: string |\n| slider.onChange | value: number |\n| checkbox.onChange | checked: boolean |\n| radio-group.onChange, segmented-control.onChange | value: string |\n| NodeGraph.onSelect | id: string |\n\nCallbacks receive values, never DOM events. Pass a setter directly or a function\nexpression; do not call it while assigning the prop. Keep handlers synchronous\nand bounded. Input/slider/checkbox keep immediate local drafts while worker state\nupdates; bind state to update other views. Choice controls require upstream state\nfor persistent selection. NodeGraph selection likewise needs a binding. No\nonSubmit, onBlur, onKeyDown, onInput, or propagation-control API exists.\n\n### Data bindings\n\nEmbed supplied JSON-compatible records in top-level const declarations; no\nautomatic external binding name exists. Read fields with dot or computed access,\nderive filtered/mapped arrays using pure expressions, and pass them to props or\neach. Treat supplied facts as read-only; use separate state for edits. Expressions\ncan read loop item/index names only within that loop\'s rendered subtree.\n\n```dil\n{@body const records = [{id:"a",name:"Alpha",amount:12}]}\n{@body const total = records.reduce((sum,item) => sum + item.amount,0)}\n<text>Total: {total}</text>\n{#each records as item}<text>{item["name"]}: {item.amount}</text>{/each}\n```\n\nBindings live only within the document. There is no host-data injection prop\nvisible to authored expressions, subscription, persistence, write-back channel,\nor fetch operation. A displayed edit is not a saved server mutation.\n\n### Host actions\n\n`GenUI.copy(text: string): undefined` requests a clipboard write, up to 65,536\ncharacters. Call it synchronously from a button or pressable onClick following\nexplicit user activation. A value-change/selection callback, initialization,\nderived getter, interpolation, or automatic execution cannot authorize copying.\nDo not defer it through promises or timers, depend on a return value, or attempt\nclipboard reads. Empty text does not produce a clipboard request.\n\n```dil\n{@body const [name,setName] = DIL.useState("")}\n{@body const valid = name.trim().length > 0}\n<input aria-label="Name" value={name} onChange={setName}/>\n{#if !valid}<caption>Enter a name.</caption>{/if}\n<button disabled={!valid} onClick={() => { if (valid) GenUI.copy(name); }}>Copy name</button>\n```\n\nThe initiating control reports Copied or Copy failed. Do not set a success flag\nbefore browser confirmation or add duplicate feedback. The platform may deny a\nvalid request. Make one copy request per action; multiple calls do not create a\nbatch. No openUrl, issueNewTurn, network, export, file creation, or storage action\nexists. Runtime resource and display limits can stop oversized/runaway documents;\ndo not approach them deliberately. The default renderer uses an opaque-origin\nframe; opt-in host/Shadow DOM modes differ in containment, and Shadow DOM is a\nstyling boundary. These modes do not grant generated source new APIs.\n\n## 7. Assets\n\n### Icons\n\n- <icon>: name:string, size?:"xs"|"lg", color?:string; children: none\n\nNames: chart-no-axes-combined, circle-check, check-circle-2, circle, wallet,\ntrending-up, users, rotate-ccw, copy, sliders-horizontal, ellipsis, sparkles,\nmouse-pointer-click, x, git-merge, package-check, shield-check, settings-2, info,\ncode-2, alert-triangle.\n\nSizes: xs=13px, omitted=17px, lg=22px. Unknown names fall back to circle; choose\nlisted names instead. Icons are decorative and cannot carry authored accessible\nlabels. Pair them with visible text or name the containing button. No external\nicon library, asset upload, or arbitrary icon URL exists.\n';
3
+ var agentSpecFull = '# GenUI Agent Specification: Full Reference\n\nUse this reference for targeted lookups. Inject [the primary specification](genui.agent.md)\nwhen the smaller instruction set is sufficient. Search `Component: NAME`,\n`Composition: NAME`, `Callback: NAME`, or `Task: NAME`. Find complete runnable\nrecipes in [the example catalog](genui.examples.md). All names are case-sensitive.\nThe numbered sections and component groups match the primary specification.\n\n## 1. Output format and safety\n\nGenerate declarative OpenDIL source. Combine ordinary Markdown with supported\ncomponents and directives. Return the source directly when asked to generate UI.\nUse a code fence only when the user asks to inspect or copy source rather than\nrender it. Do not include an explanation of how to install React, a component\nmodule, a package manifest, or a web page around a generated interface.\n\nTreat the supported vocabulary as closed unless the host explicitly supplies a\ncustom component contract. A familiar HTML, React, Recharts, or SVG API is not\nautomatically an OpenDIL API. Match every tag, prop, callback name, and data shape\nin this reference. A tag being accepted by the parser does not establish that a\nrenderer exists for it. An unknown prop may be ignored rather than reported.\nGenerate valid output deliberately instead of depending on fallback behavior.\n\nUse Markdown for prose, real components for controls, and directives for UI\nstructure. Do not encode an entire interface as a string expression. Strings\nreturned by expressions are displayed as text, not parsed as nested DIL. Do not\nconstruct HTML strings, use `dangerouslySetInnerHTML`, or request arbitrary CSS.\nThere is no authorable HTML document, React component function, import statement,\nstylesheet, or JavaScript module boundary.\n\nClose elements and control directives in the reverse order in which they open.\nWrite leaves as self-closing tags. Finish incomplete tokens before ending the\nresponse. Keep the source readable enough that a later agent can locate a binding\nor handler. Prefer one declaration per line and modest component trees. Avoid\ndeep wrappers that add no layout, semantics, or interaction value.\n\nUse only facts supplied by the user or the enclosing application. Label synthetic\nexamples, estimated totals, and placeholder illustrations appropriately. Do not\npresent a disconnected chart as live telemetry or a local form as a completed\nserver submission. Render supplied source titles and URLs accurately. Do not\ninvent citation IDs, external services, host actions, or automatic data refresh.\n\nGive controls meaningful names. Use visible labels where possible and explicit\n`aria-label` on controls that expose it. Keep status text next to status colors.\nProvide textual summaries for charts, SVG drawings, and node graphs. An icon is\ndecorative; it cannot replace the name of an action. Avoid interactive descendants\ninside an interactive ancestor, including buttons inside pressable cards.\n\nKeep data transformations bounded. Prefer a short filter, map, or reduce over\nrecursive traversal or large generated allocations. Do not run arbitrary code\nreceived in a data record. Never use an expression to discover undocumented host\nglobals or alter the execution environment. Do not use `eval`, `Function`, dynamic\nimports, or VM implementation globals in authored output.\n\nExecution boundaries:\n\n| Surface | Supported author behavior |\n| --------------------------- | ------------------------------------------------------------ |\n| Markdown and component tree | Declare content and supported props |\n| QuickJS worker | Evaluate expressions, declarations, and supported callbacks |\n| Renderer | Present approved widgets and dispatch their supported events |\n| Host boundary | Receive explicitly authorized clipboard requests |\n| Server | No generated server code or server action API |\n\nThe document expression environment does not expose browser `window`, `document`,\nDOM nodes/events, `fetch`, XMLHttpRequest, WebSocket, localStorage, IndexedDB,\nbrowser timers, or Node facilities. Do not assume that because the renderer uses\nthese internally, document expressions can call them. Native JavaScript features\nsuch as arrays, objects, functions, and arithmetic remain available inside QuickJS.\nThe prohibition on `eval` and `Function` is an authoring rule; do not describe it\nas a proven removal of those primitives from the VM.\n\nThe default renderer uses an opaque-origin frame. Host DOM and Shadow DOM modes\nare explicit consumer choices with different containment properties. Shadow DOM\nprovides styling separation, not iframe containment. Generated source cannot\nselect a rendering mode or authorize new APIs. Do not tell a user to weaken\ncontainment to make an unsupported feature work.\n\nResource constraints are bounds, not generation targets. Current VM limits are\n64 MiB heap, 64 KiB stack, and an interpreter interrupt after more than 256 polls.\nThe worker transport also has a 1-second timeout. There is no promised 50 ms\nevaluation budget. Execution speed depends on the device and work performed.\nEncoded results and dependency metadata are limited to 524,288 characters each;\nencoding rejects excessive structural depth. Keep data and calculations small.\nDisplay limits can stop a document even when its JavaScript evaluation succeeds.\n\n#### Task: output-review\n\nBefore finishing, check that every used tag and prop appears in this reference,\nevery named binding is declared before its consumer, each callback accepts the\ndocumented value type, all control branches close, and every displayed claim is\nsupported by supplied data. Remove inert action buttons unless they intentionally\ndemonstrate appearance. Do not add an implementation checklist to the generated UI.\n\n## 2. Syntax and parsing\n\n### Markdown\n\nWrite paragraphs, headings, ordered/unordered lists, emphasis, blockquotes, code\nfences, and GitHub-flavored tables, task lists, and strikethrough. Use Markdown\nheadings for the overall document outline. A DIL title is a styled h3 and does\nnot choose an arbitrary heading level. Use ordinary prose when no special layout\nor control is needed.\n\nSeparate paragraphs and major blocks with blank lines. Keep indentation consistent\nwithin component children; the renderer normalizes Markdown indentation but is\nnot an MDX compiler. Avoid relying on a large indentation offset to create code\nblocks inside a layout. Use explicit fences or CodeBlock for source displays.\n\nMarkdown links are deliberately displayed as inert text spans containing their\nlabels. They do not open their href. Markdown images are suppressed. Use a visible\nplain-text URL if the reader needs the destination, and do not promise that\nclicking it navigates. There is no DIL anchor or image tag to restore browser\nbehavior. Bare URLs can be recognized by GFM but still render without navigation.\n\nTask-list checkboxes are Markdown presentation. They do not provide onChange,\nstate binding, or an action target. Use the checkbox component for user-editable\nchoices. A Markdown table is useful for ordinary tabular prose; use the DIL table\ncomposition when cells contain components or reactive controls.\n\nFenced code protects its contents from DIL parsing. Put triple backticks or triple\ntildes at the beginning of a line, with no more than three preceding spaces.\nClose the fence with the same marker on a line of its own. A longer fence, such as\nfour backticks, can enclose lines that start with three.\nA `mermaid` language fence renders a Mermaid diagram rather than ordinary code.\nOther language labels request display syntax, not code execution.\n\nInline code spans follow Markdown: a run of one or more backticks opens a span\nthat the next run of the same length closes. Braces, tags, and directives inside\na span display literally and never evaluate, so `{ leading: false }` or `<div>`\nin backticks is safe in prose. A span cannot cross a blank line or continue into\na line that starts another block: a list item, heading, blockquote, fence,\ncomponent tag, or block directive such as `{:else}`. A component tag later on\nthe same line stays inside the span. An unmatched backtick protects nothing, and\na backslash before a backtick makes it literal. A closing fence may be followed\non its line by a component closing tag or block directive.\n\nLowercase HTML-like tags that are not DIL tags, such as `<div>`, `</span>`, or\n`<br/>`, display as plain text up to their closing `>`, and so do autolinks such\nas `<https://example.com>`. Their quoted or braced attribute values stay text,\nbut any other brace is an expression again, so `a<b then {total}` shows the\nvalue. Do not rely on this to format output; use Markdown or DIL components. A\ncapitalized tag that is not a supported component renders an\nunsupported-component error in its place. To insert a brace in prose, interpolate\na string containing it. Entity spellings can have Markdown-dependent display\nbehavior; use a string expression when exact text matters.\n\n```dil\n# Review summary\n\n**Ready** for review. The sample contains synthetic values.\n\n- Static prose uses Markdown.\n- Interactive choices use supported components.\n\n| Item | Value |\n| --- | --- |\n| Example records | 2 |\n\n<text>A literal brace: {"{"}</text>\n```\n\nMarkdown expressions are inserted as text after Markdown parsing. Do not expect a\nstring containing `**bold**` to become emphasis, a string containing a tag to\nbecome a component, or an interpolated URL to become a live link. Put the needed\nformatting around the expression in authored source instead.\n\n### JavaScript expressions\n\nUse `{expression}` in text or `property={expression}` in attributes. The outer\nbraces delimit JavaScript; an object value therefore needs its own object braces,\nas in `content={{chartType:"bar",data:[]}}`. Numbers written in quoted attributes\nremain strings. Supply numeric props with braces, including slider min/max/step,\nlayout spacing, dimensions, and SVG numeric coordinates.\n\nAttribute forms:\n\n| Form | Meaning |\n| -------------------------------------- | ------------------- |\n| `color="secondary"` | String literal |\n| `color=\'secondary\'` | String literal |\n| `border` | Boolean true |\n| `border={false}` | Boolean false |\n| `padding={4}` | Number |\n| `value={name}` | Evaluated binding |\n| `onChange={setName}` | Callback reference |\n| `onClick={() => setCount(n => n + 1)}` | Function expression |\n\nQuoted attributes use a simple delimiter scan. Do not rely on JavaScript-style\nbackslash escaping inside a quoted attribute. For text containing its surrounding\nquote, use a JavaScript string expression. Do not repeat an attribute; the parser\ncan overwrite earlier entries, which is not a useful generation contract.\nUnquoted scalar values, JSX spread syntax, shorthand object props, and arbitrary\nattribute fragments are unsupported.\n\nExpressions use ordinary JavaScript arithmetic, comparisons, logical operators,\nternaries, optional chaining, nullish coalescing, property access, computed property\nnames, string/array/object literals, template strings, and functions. Array\nfilter/map/reduce/find/some/every and string transformations work as JavaScript\noperations. Keep transformations pure and their output JSON-compatible.\n\n```dil\n{@body const item = {name:"Ada",hours:3,rate:20}}\n{@body const field = "name"}\n<text>{item[field]}: {item.hours * item.rate}</text>\n<caption>{`Hours: ${item.hours}`}</caption>\n<input aria-label="Quoted example" value={\'Say "hello"\'} disabled/>\n```\n\nInterpolation display:\n\n| Evaluated value | Text output |\n| ----------------------- | ------------------- |\n| String or finite number | Its displayed value |\n| true / false | `true` / `false` |\n| null / undefined | Empty text |\n| Object or array | `[object Object]` |\n\nUse `items.join(", ")` for a text list, `JSON.stringify(record)` for intentionally\ndisplayed JSON, or an each directive for repeated UI. Arrays returned by map do\nnot become React children. JavaScript cannot contain authored JSX elements.\nDo not create UI using string concatenation and expect interpolation to parse it.\n\nThe bridge serializes data using JSON and represents callback functions with\ninternal handles. Do not author or inspect those handles. Avoid circular records,\nBigInt, sparse data that relies on undefined, Map/Set instances, prototype-based\nobjects, or objects with behavior in serialization. Non-finite numbers do not\nretain useful numeric meaning across JSON serialization. Use plain records,\narrays, strings, booleans, null, and finite numbers.\n\nKeep statements out of expression positions. Assignments and updates may be valid\nJavaScript expressions but are forbidden generation patterns during rendering.\nUse callback bodies for state changes. A handler may use local const declarations,\nan if guard, and a bounded loop, but simpler immutable transformations are preferred.\nDo not use top-level await, imports, exports, or async resource work.\n\n`Intl.NumberFormat` is a limited host bridge. Its format operation uses en-US\nformatting with maximumFractionDigits=0; supplied locale and options do not\nconfigure the formatter. It is not a full Intl implementation. For fixed decimal\nprecision, use a bounded numeric expression and `.toFixed(n)`. Do not promise\ncurrency/locale behavior from the bridge that the implementation does not provide.\n\n#### Task: format-values\n\n```dil\n{@body const amount = 1234.5}\n<text>{new Intl.NumberFormat().format(amount)}</text>\n<caption>{amount.toFixed(2)} units</caption>\n```\n\n### State declarations\n\nUse one `{@body ...}` directive for each declaration. Place declarations before\nthe interface. The supported forms are deliberately narrower than a JavaScript\nprogram body:\n\n```text\n{@body const [name,setName] = DIL.useState(initialValue)}\n{@body const name = expression}\n```\n\nAn optional final semicolon is accepted. Use names beginning with a letter or\nunderscore and containing only letters, digits, and underscores. Avoid keywords,\nduplicate names, builtin names, DIL, GenUI, and implementation-like double-underscore\nnames. Though some JavaScript identifiers allow `$` or Unicode, declaration\nrecognition is narrower; use the stated subset for reliable generation.\n\nOnly the exact state-pair destructuring shape is supported. Do not omit the setter,\nadd a third item, destructure objects, use nested patterns, or declare several\nbindings in one directive. Ordinary const declarations create derived expression\nbindings. There is no let/var declaration mode, function statement declaration,\nclass statement, or arbitrary script block. A function can be a const expression.\n\nState initialization is once per state name in the mounted document. An initializer\nmay be a value or a function returning the initial value. Keep it side-effect-free.\nDo not put a clipboard operation or setter call in initialization. State setters\naccept either a replacement value or an updater function receiving the previous\nvalue. A function passed to the setter is treated as an updater; do not use state\nas a general function store.\n\nOrdinary const bindings are getters. Their expression is recomputed when read;\nthey are not once-only snapshots and do not memoize expensive work. A getter can\nread state and other bindings. Keep dependency order straightforward and avoid\ncycles. A derived callback can be declared as a const function expression and\npassed to a supported event prop.\n\n```dil\n{@body const [quantity,setQuantity] = DIL.useState(() => 2)}\n{@body const unitPrice = 15}\n{@body const total = quantity * unitPrice}\n{@body const addOne = () => setQuantity(previous => previous + 1)}\n<button onClick={addOne}>Add one</button>\n<text>{quantity} items: {total} units</text>\n```\n\nAll body declarations belong to the document, even when their source is written\ninside a conditional or each block. Parsing collects declarations independently\nof which visual branch later renders. A declaration inside a loop does not run\nonce per item and does not inherit item/index bindings. Generate unconditional\ntop-level declarations and keep per-item state in a top-level keyed object/array.\n\nDo not rely on duplicate state declarations to reset a value. A matching existing\nstate name retains state; collisions between state, setter, and derived names can\nfail or redefine bindings. Give each state pair and derived binding a unique name.\nUse a reset button calling the setter when a reset is required.\n\nNo useEffect, useMemo, useCallback, useRef, or useId hook is exposed to DIL source.\nThe renderer may use React hooks internally; they are not document hooks. Do not\ntranslate a React example into DIL by retaining arbitrary hook calls. Replace\ncomputed values with const getters and user effects with supported event handlers.\n\n### Conditional rendering\n\nUse `{#if condition}`, optional `{:else if condition}` branches, optional\n`{:else}`, and `{/if}`. Conditions use JavaScript truthiness. The first matching\nbranch is selected. With no match and no else, nothing renders. Keep else-if and\nelse within their enclosing if and close nested branches before outer branches.\n\n```dil\n{@body const [level,setLevel] = DIL.useState(0)}\n<slider aria-label="Level" min={0} max={10} step={1} value={level} onChange={setLevel}/>\n{#if level >= 8}\n <badge color="warning">High</badge>\n{:else if level > 0}\n <badge color="success">Active</badge>\n{:else}\n <caption>Not started</caption>\n{/if}\n```\n\nA conditional changes visibility, not declaration scope or document state lifetime.\nHiding an input does not erase its top-level state. If the next interaction needs\na reset, perform that reset explicitly in a callback. Keep data guards before\nunsafe property reads inside rendered expressions; the renderer can evaluate\nbranch conditions while resolving which branch to present.\n\nRepeat with `{#each expression as item}` or\n`{#each expression as item,index}` and close with `{/each}`. The expression should\nevaluate to an array. Non-arrays currently produce no items rather than a typed\nerror. Do not depend on that fallback to represent loading or a failed request.\nUse an explicit empty-array branch and truthful status text.\n\nWithin repeated rendered content, item is the current value and index is its\nzero-based position. Nested repeats can read outer scope bindings. Choose\ndifferent variable names for outer and inner items to avoid accidental shadowing.\nDeclare shared transformations outside the repeat only when they do not need an\nitem binding. Otherwise compute the small expression inline.\n\nUse stable unique string or numeric `id` properties on repeated objects. Without\nsuch an ID, identity falls back to index. Reordering a positional list can attach\nlocal widget state to a different record. The language has no key prop, keyed-each\nsuffix, or custom key callback. Do not invent one. Allocate IDs when creating new\nrecords, not from the current array position after filtering.\n\n```dil\n{@body const groups = [{id:"g1",name:"Review",items:[{id:"a",name:"Alpha"}]}]}\n{#each groups as group}\n <box border padding={3}>\n <title>{group.name}</title>\n {#each group.items as entry,index}\n <text>{index + 1}. {entry.name}</text>\n {/each}\n </box>\n{/each}\n```\n\nStreaming rules:\n\n- Append source suffixes while preserving every previous character.\n- Close useful children as they arrive; an enclosing layout may remain open.\n- Leave incomplete tokens pending only while more source will follow.\n- Close an each block before expecting its repeated template to display.\n- End with a complete document; completion drops unfinished tokens and marks the\n answer incomplete.\n- Use callbacks and state for interaction; do not patch earlier streamed source.\n\nThe parser retains lexical state across chunk boundaries, including quoted strings,\ntemplates, comments, and regular expressions inside braces. There is no need to\nalign transport chunks with tokens. Generation must still produce conventional,\nbalanced syntax. Do not count a recoverable partial prefix as valid final output.\nRepeat templates wait for their closing directive so the renderer does not mount\nlarge numbers of incomplete copies.\n\n#### Task: incomplete-stream\n\nAn unfinished first chunk may be:\n\n```text\n<box padding={\n```\n\nAppend `4}><text>Ready</text></box>` and then signal completion. The finished source is:\n\n```dil\n<box padding={4}><text>Ready</text></box>\n```\n\nSource replacement, document/message identity changes, and remounting can create a\nnew document and reset state. Ordinary suffix appends and virtualized offscreen\nunmounts retain document-owned state. Do not use internal render timing or viewport\nvisibility as an authoring lifecycle API.\n\n## 3. Component API\n\nRead each property block literally. `(optional)` means the property may be omitted;\n`default` describes the widget\'s current fallback. `(required for generation)`\nmeans supply a meaningful value even if the permissive renderer has a fallback.\nDefaults do not replace type correctness. A string `"false"` is not boolean false.\n\nChildren categories: inline = text, inline Markdown, and inline components; generic\n= inline or block content; raw = literal source; none = no content. Named children\nrestrict direct child component types. Whitespace and control directives may\nsurround named children. These contracts guide generation; the parser is not an\nelement-specific schema validator. Do not use parser acceptance as evidence of\nvalid browser structure.\n\nShared layout props:\n\n```text\npadding: number | {x?:number,y?:number} (optional)\ngap: number (optional)\nradius: "sm" | "md" | "lg" | "xl" | "2xl" | "full" | string (optional)\nborder: boolean | {size?:number,color?:string} (optional)\nbackground: string (optional)\nclip: boolean (optional)\nwidth: number | string (optional)\nmaxWidth: number | string (optional)\nheight: number | string (optional)\nflex: number | string (optional)\ncolumns: number (optional)\nalign: string (optional)\njustify: string (optional)\nwrap: "wrap" (optional)\n```\n\nOnly components whose Properties block lists `layout` consume these props. A table\ndoes not become a layout container merely because table-cell accepts layout props.\nText, button, input, chart, and other components do not automatically accept them.\nWrap a component in box/row/grid when the surrounding layout needs control.\n\nNumeric padding and gap use four-pixel units: 1=4px, 2=8px, 3=12px, 4=16px.\nAn x/y padding object sets inline/block padding independently. It does not accept\ntop/right/bottom/left keys. Numeric width, height, and maxWidth are pixels. String\ndimensions may use valid CSS lengths or percentages. Flex follows CSS flex values;\nit is not a width unit. Do not emit numeric strings when a number was intended.\n\nNamed radii: sm=4px, md=6px, lg=8px, xl=12px, 2xl=16px, full=9999px. A custom\nstring radius is passed as a CSS border radius; use a simple valid value. The\nnames are DIL names, not assumptions about another design system\'s scale.\nBorder true enables a 1px theme border. An object may change size and color.\nBorder false/omitted disables this authored border. Keep widths finite and positive.\n\nUse semantic color tokens: default, primary, secondary, tertiary, success, warning,\ndanger, surface-secondary, surface-tertiary, subtle, strong. A valid CSS color is\nalso accepted when shorter than 128 characters and free of URL/custom-variable\nor declaration syntax. A color object, gradient, arbitrary theme variable, or\nstylesheet string is not accepted. Invalid colors are ignored rather than repaired.\n\nUse align start/center/end/stretch for item alignment. Start/end map to flex-start/\nflex-end. Use justify start/center/end/between for common distribution; between\nmaps to space-between. The reader accepts strings beyond these recommendations,\nbut a browser may reject them. Keep generation to meaningful CSS alignment values.\nUse wrap="wrap" only when the layout benefits from wrapping.\n\nColumns sets a responsive grid\'s requested column count. It is not a general\nchild-span/placement API. Use a small positive integer. The stock grid reduces\ncolumns on narrow screens. A layout prop can be accepted by a shared reader\nwithout changing a component that does not use the corresponding CSS behavior.\nFor example, columns does not turn a row into a grid.\n\n### Text components\n\n#### Component: text\n\n```text\nProperties:\n color: string (optional; inherited color when omitted)\n size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (optional; inherited size)\n weight: "medium" (optional)\n tabularNums: boolean (optional; default false)\n\nChildren: inline\n```\n\nRender a span-like text value. Use it for a value inside a row, a short reactive\nsentence, or a styled phrase. Text does not accept layout props, an arbitrary\nstyle object, href, or a strong prop. Use Markdown emphasis in children when bold\ntext is needed. Weight medium maps to 500. Other weight strings do not expose a\ngeneral font-weight API.\n\nThe size scale is xs=12px, sm=14px, md=16px, lg=18px, xl=24px, 2xl=30px at the\nnormal 16px root. tabularNums requests tabular numeral shapes; it does not format\nnumbers or align decimal places automatically. Format the expression separately.\nKeep nested content inline; use box for a paragraph containing blocks.\n\n```dil\n{@body const revenue = 1234.5}\n<text size="lg" weight="medium" tabularNums>{revenue.toFixed(2)} units</text>\n```\n\n#### Component: title\n\n```text\nProperties:\n color: string (optional)\n size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (optional; default lg)\n weight: "medium" (optional; consumed but does not override title weight)\n tabularNums: boolean (optional; default false)\n\nChildren: inline\n```\n\nRender a styled h3 with weight 600, default size 18px, compact line height, and no\ndefault margin. A weight prop is consumed by the shared text branch but the title\nkeeps weight 600. Do not use it to request a different heading rank. For a document\nwith h1/h2 hierarchy, use Markdown headings. Use title for a card or panel heading.\nAn explicit size can change appearance without changing the heading\'s rank.\n\nKeep controls outside the title; compose title and actions as siblings in a row.\nDo not rely on a title prop to associate it with a dialog, table, or input. Those\nassociations are not exposed by the DIL API. Give the surrounding content a clear\nreading order using ordinary source order.\n\n#### Component: caption\n\n```text\nProperties:\n color: string (optional; default secondary)\n size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (optional; default xs)\n weight: "medium" (optional)\n tabularNums: boolean (optional; default false)\n\nChildren: inline\n```\n\nRender small secondary text, defaulting to 12px. Use it for units, context, helper\nmessages, or a short validation message. It is a text span, not a live-region,\ntooltip, accessible description binding, or hidden-label mechanism. Keep messages\nvisible and sufficiently descriptive without claiming automatic announcement.\n\nUse an explicit danger/warning color only when the text explains the state. A\nred caption alone is not form validation; derive a validity value and guard the\naction. Avoid shrinking essential instructions merely to fit a narrow layout.\n\n#### Component: badge\n\n```text\nProperties:\n color: string (optional)\n\nChildren: inline\n```\n\nRender a compact status label. Success, warning, and danger colors receive related\nbackground treatment. Other accepted colors affect foreground but do not create\narbitrary background variants. There is no variant, size, icon, or onClick prop.\nPlace an icon in children when needed and keep visible status text beside it.\n\nDo not make a badge look like a selectable control. Use button, checkbox, radio,\nor segmented-control for input. For a changing status, render the badge from state\nor an if directive. Labels such as Saved must reflect an actual supported action;\ncopying text is not a saved-server mutation.\n\n#### Component: label\n\n```text\nProperties: none\n\nChildren: inline\n```\n\nRender medium-weight visual label text. It is a styled span and has no for/id\nassociation props. Pair it with input aria-label using the same visible words.\nDo not claim that clicking this component focuses a separate input. Checkbox and\nradio provide their own clickable label composition through their children.\n\nUse label for a compact field heading or a value-group label. It cannot take\nlayout, color, or size props. Wrap it in a suitable layout instead of inventing\nstyling attributes. Keep the visible label stable while validation messages change.\n\n#### Component: CodeBlock\n\n```text\nProperties:\n language: string (optional; default empty string)\n editable: boolean (optional; default false)\n\nChildren: raw\n```\n\nPlace source directly between opening and closing tags. Everything is literal\nuntil the exact `</CodeBlock>` delimiter: braces, tags, and directives inside are\nnot evaluated. The source prop does not exist. Do not nest DIL components to\nformat the source. The display trims leading/trailing whitespace when no draft\nexists, so do not use it for byte-exact whitespace preservation requirements.\n\nEditable true exposes an internal text editor. Edits remain local to this widget\'s\ndocument draft store. They do not run, update DIL state, call an authored handler,\nor create a downloadable file. There is no onChange/value/defaultValue API. Choose\ninput for an authored string value and CodeBlock for editable source presentation.\n\nThe widget provides copy and word-wrap controls. Copy is user-triggered and can\nfail due to clipboard permissions. Its built-in feedback reports that outcome.\nDo not wrap the code block in another action control or duplicate its copy button\nunless the separate action has a distinct task. Code copying is subject to the\n65,536-character clipboard limit; source display is limited to 131,072 characters.\n\n```dil\n<CodeBlock language="javascript" editable>\nconst greeting = "Hello";\nconsole.log(greeting);\n</CodeBlock>\n```\n\nDo not include the exact closing delimiter inside its raw source; it terminates\nthe component even if it occurs in a quoted source-language string. Use a fenced\ncode block for examples that need to show the delimiter literally. Language is a\ndisplay hint, not a compiler selection or permission to execute code.\n\n### Media components\n\n#### Component: AsyncImage\n\n```text\nProperties:\n query: string (required for generation)\n\nChildren: none\n```\n\nRender an offline, locally constructed placeholder illustration with query as\nalt text. The name does not imply remote search, asynchronous model generation,\nor retrieval of a verified image. The stock implementation builds a simple SVG\nlandscape; query text only influences a small set of color choices. Do not use it\nas evidence of an actual person, place, product, or event.\n\nThe placeholder uses a 16:9 wrapper and built-in rounding. There is no src, alt,\nwidth, height, fit, loading, or onLoad prop. Size the surrounding layout if needed.\nIf the browser cannot load the constructed image, the widget displays Image\nunavailable. Do not set your own loaded flag; no authored load callback exists.\n\n```dil\n<box maxWidth={480}>\n <AsyncImage query="Placeholder illustration of a mountain landscape"/>\n <caption>Illustrative placeholder, not a photograph.</caption>\n</box>\n```\n\nA host may override components under an explicitly supplied contract. That does\nnot change the stock contract documented here. Do not assume a host override can\nsearch the web or load a supplied URL unless the prompt states that capability.\nNo stock video, audio player, file preview, or upload component is available.\n\n### Layout components\n\n#### Component: box\n\n```text\nProperties:\n layout\n\nChildren: generic\n```\n\nUse box for vertical flow, panels, and card surfaces. Children retain their source\norder. A box with border/padding/radius/background can present a card without\ninventing a card component. Keep a card\'s title, body, and actions as readable\nsiblings. Set maxWidth when a form or card should remain narrow on a wide screen.\n\nBox participates in document flow and may virtualize long child sequences. Do not\nassume every offscreen child is simultaneously mounted. Document state survives\nthat presentation behavior. Do not use viewport-dependent expression effects or\nDOM queries to coordinate children. Use declared state and bindings.\n\n#### Task: static-card\n\n```dil\n<box border padding={4} radius="xl" gap={3} maxWidth={480}>\n <title>Release review</title>\n <text>Ready for the next review.</text>\n <badge color="success">Prepared</badge>\n</box>\n```\n\n#### Component: row\n\n```text\nProperties:\n layout\n\nChildren: generic\n```\n\nUse row for horizontal siblings such as a title and action, icon and value, or a\nshort control group. Set align for vertical alignment and gap for spacing.\nUse wrap="wrap" when labels or controls may exceed available width. Avoid fixed\nheights for rows with wrapping content. A narrow display must retain all controls.\n\nUse justify="between" for two groups or spacer for flexible separation. Do not\ninsert literal spaces to align components. For multi-column data that needs\nconsistent row/cell relationships, use a table rather than independent rows.\n\n#### Component: grid\n\n```text\nProperties:\n layout\n\nChildren: generic\n```\n\nUse grid for a responsive set of peers. Set columns to a small positive integer\nand gap to the desired spacing unit. The stock grid reduces the requested column\ncount to one at viewport widths of 520px or less. Do not compute viewport breakpoints in document\nJavaScript; browser dimensions are not exposed.\n\nGeneric children are accepted; grid-item is available when a child needs its own\nlayout props. There is no template-string API, row-span, column-span, area name,\nor media-query prop. A grid-item does not add a missing placement API. Keep the\nsource order meaningful for a single-column reading order.\n\n#### Component: grid-item\n\n```text\nProperties:\n layout\n\nChildren: generic\n```\n\nUse inside grid when a cell needs padding, border, background, or a nested layout.\nIt is a generic layout wrapper and does not expose grid coordinates or spanning.\nThe renderer does not require it around every grid child. Avoid a wrapper when\nthe child already owns its necessary layout.\n\n#### Composition: grid > grid-item\n\n```dil\n<grid columns={2} gap={3}>\n <grid-item border padding={3} radius="lg">\n <title>Alpha</title><text>12 sample units</text>\n </grid-item>\n <grid-item border padding={3} radius="lg">\n <title>Beta</title><text>18 sample units</text>\n </grid-item>\n</grid>\n```\n\n#### Component: spacer\n\n```text\nProperties: none\n\nChildren: none\n```\n\nUse as a flexible child in a row to consume remaining space. It does not accept a\nsize, height, width, or direction prop. Use layout gap/padding for fixed spacing.\nAn isolated spacer in ordinary vertical content does not promise a fixed blank\nregion. Keep spacing intent on the parent whenever possible.\n\n#### Component: divider\n\n```text\nProperties: none\n\nChildren: none\n```\n\nRender a standard separator. No orientation, thickness, color, or layout props\nare exposed. Use it between meaningful groups rather than after every line.\nDo not place it directly among table rows or radio children; those parents require\ntheir named child types. Put separation inside a cell/content region if needed.\n\n#### Component: table\n\n```text\nProperties: none\n\nChildren: table-row\n```\n\nThe renderer supplies the body element. Do not emit table-section, tbody, thead,\ntr, td, or th. DIL table has no column sizing, header, dividers, or caption prop.\nDescribe the table with nearby text/title and use a first row of readable labels\nwhen using component cells. For ordinary header semantics and prose-only cells,\nprefer a Markdown table.\n\nKeep row widths consistent by generating the same number of cells. There is no\ncolSpan or rowSpan. Use a two-column key/value table instead of inventing spanning\nto present irregular data. For empty data, render a caption outside the table\nthrough a conditional rather than inserting arbitrary text directly into it.\n\n#### Component: table-row\n\n```text\nProperties: none\n\nChildren: table-cell\n```\n\nPlace directly under table, optionally produced by each/if directives. It has no\nselected, header, background, onClick, or layout API. If a row needs an action,\nplace a button inside a cell. A pressable cannot replace the structural row.\nDo not wrap rows in box or grid-item under table.\n\n#### Component: table-cell\n\n```text\nProperties:\n layout\n\nChildren: generic\n```\n\nPlace directly under table-row. Cells may contain text, badges, nested layout,\ncontrols, or a small chart. Layout props style the cell; they do not change table\nstructure. There is no align prop with text-alignment semantics beyond the shared\nlayout reader, no colSpan/rowSpan, and no header role selection. Use nested rows\nor text formatting only when their actual contract meets the task.\n\n#### Composition: table > table-row > table-cell\n\n```text\n<table>\n children: table-row\n <table-row>\n children: table-cell\n <table-cell>\n children: generic\n```\n\n```dil\n{@body const records = [{id:"a",name:"Alpha",amount:12},{id:"b",name:"Beta",amount:18}]}\n<table>\n <table-row><table-cell><text weight="medium">Name</text></table-cell><table-cell><text weight="medium">Amount</text></table-cell></table-row>\n {#each records as item}\n <table-row><table-cell>{item.name}</table-cell><table-cell><text tabularNums>{item.amount}</text></table-cell></table-row>\n {/each}\n</table>\n```\n\n#### Component: popover\n\n```text\nProperties: none\n\nChildren: popover-trigger | popover-content\n```\n\nCompose one trigger region and one content region. Open/close behavior belongs to\nthe stock overlay. No open/defaultOpen/onOpenChange prop is exposed to DIL. Do not\nadd state solely to imitate the existing trigger behavior. Place related optional\ndetails or controls in the content and keep the triggering label meaningful.\n\n#### Component: popover-trigger\n\n```text\nProperties: none\n\nChildren: one button\n```\n\nPlace exactly one button inside. The trigger context composes that button with\nthe overlay behavior; it does not make an arbitrary box or text node a trigger.\nThe button can have normal button props. It needs no onClick to open the popover.\nAvoid combining unrelated privileged work with merely opening optional details.\n\n#### Component: popover-content\n\n```text\nProperties:\n side: "top" | "bottom" (optional; default bottom)\n align: "end" | "center" (optional; default center)\n\nChildren: generic\n```\n\nPlace directly under popover. The widget bounds content to the viewport. It has\nno width, padding, layout, modal, placement-offset, or animation prop. Put a box\ninside when the content needs layout. Side values other than top fall back to\nbottom; align values other than end fall back to center. Generate only the stated\nvalues. Content can contain inputs or actions as siblings in a normal layout.\n\n#### Composition: popover > popover-trigger + popover-content\n\n```text\n<popover>\n children: popover-trigger | popover-content\n <popover-trigger>\n children: one button\n <popover-content>\n children: generic\n```\n\n```dil\n<popover>\n <popover-trigger><button variant="outline">Details</button></popover-trigger>\n <popover-content side="bottom" align="end">\n <box gap={2}><title>Review notes</title><text>No additional action is required.</text></box>\n </popover-content>\n</popover>\n```\n\n#### Component: carousel\n\n```text\nProperties: none\n\nChildren: carousel-item\n```\n\nRender a horizontal item collection with built-in previous/next controls. Keep\nitems as direct children. There is no activeIndex, items data prop, onChange,\nautoplay, orientation, or slide-size API. Do not use it to represent a required\nstepper whose progression must be controlled by validation.\n\n#### Component: carousel-item\n\n```text\nProperties: none\n\nChildren: generic\n```\n\nPlace under carousel. Each slide has a stock width and vertical content wrapper.\nUse a box inside for border/padding/background customization. A carousel-item\ndoes not accept layout props itself. Keep items understandable independently and\navoid placing essential instructions only on an undiscovered later slide.\n\n#### Composition: carousel > carousel-item\n\n```text\n<carousel>\n children: carousel-item\n <carousel-item>\n children: generic\n```\n\n```dil\n<carousel>\n <carousel-item><box border padding={4}><title>Alpha</title><text>First option.</text></box></carousel-item>\n <carousel-item><box border padding={4}><title>Beta</title><text>Second option.</text></box></carousel-item>\n</carousel>\n```\n\n### Input components\n\n#### Component: button\n\n```text\nProperties:\n aria-label: string (optional)\n disabled: boolean (optional; default false)\n variant: "outline" | "ghost" | "default" (optional; default default)\n size: "sm" | "xs" | "default" (optional; default default)\n block: boolean (optional; default false)\n onClick: callback () => void (optional)\n\nChildren: inline\n```\n\nUse for explicit actions. Inline children may include icon and text. Give icon-only\nbuttons aria-label; keep the name about the action rather than the icon. A label\nfallback exists for some stock source patterns, but generation must provide a\nclear name instead of depending on those demo-oriented fallbacks.\n\nDefault is a filled action, outline is bordered, and ghost is low-chrome. Unknown\nvariant or size strings fall back to default; do not generate unsupported styles.\nBlock makes the button full-width. There is no href, type, loading, icon prop,\nlayout prop set, or arbitrary DOM event forwarding. Buttons are not form submits.\n\nThe authored disabled prop and runtime readiness both affect availability. A\nstreaming or stopped document may keep a control unavailable even when disabled\nis false. Do not use enabled appearance as proof that an expression has completed.\nKeep handler logic safe independently of a disabled UI guard.\n\n```dil\n{@body const [count,setCount] = DIL.useState(0)}\n<button variant="outline" onClick={() => setCount(previous => previous + 1)}>\n <icon name="mouse-pointer-click"/> Increment\n</button>\n<text>{count}</text>\n```\n\n#### Component: pressable\n\n```text\nProperties:\n layout\n color: string (optional)\n onClick: callback () => void (optional)\n\nChildren: generic\n```\n\nRender a button-like full-card action whose children may include noninteractive\nlayout and block content. Keep the action name visible in its content. There is\nno authored aria-label or disabled prop. Do not add them just because the backing\nelement is a browser button. Use button when a task needs authored disabled state.\n\nNever nest buttons, inputs, radio groups, checkbox, links, or another pressable\ninside. Place secondary actions beside the pressable, not inside its clickable\nsurface. Layout props apply to the surface; color affects foreground. The widget\nprovides the same action clipboard feedback as button for supported copy actions.\n\n#### Component: input\n\n```text\nProperties:\n aria-label: string (optional in API; supply for generation)\n value: string (optional; default empty string)\n placeholder: string (optional; default empty string)\n disabled: boolean (optional; default false)\n onChange: callback (value:string) => void (optional)\n\nChildren: none\n```\n\nUse as a single-line string input. Bind value and onChange to document state when\nother content depends on edits. OnChange receives a string, not a DOM event. There\nis no type, numeric parsing, email mode, required, pattern, minLength, maxLength,\nautoComplete, onBlur, or onKeyDown prop. Use explicit string validation and number\nconversion in derived expressions if the task requires them.\n\nPlaceholder is a hint, not a persistent accessible label. Provide aria-label and,\nwhen useful, a sibling label with matching words. The visual label component does\nnot associate itself through an ID. Keep validation messages as visible siblings.\n\nThe widget holds immediate local text drafts while worker updates are acknowledged,\nincluding composition input. That does not create a document binding when no\nonChange/setter exists. Bind state deliberately rather than reading DOM state.\nAvoid assuming that a local field draft is persisted beyond the document.\n\n#### Component: slider\n\n```text\nProperties:\n aria-label: string (optional in API; supply for generation)\n min: number (optional; default 0)\n max: number (optional; default 100)\n step: number (optional; default 1)\n value: number (optional; default 0)\n marks: {label:string}[] (optional; default no marks)\n disabled: boolean (optional; default false)\n onChange: callback (value:number) => void (optional)\n\nChildren: none\n```\n\nUse a finite numeric range with min < max and step > 0. Keep value within the\nrange and choose an initial value aligned with the intended step. The widget\naccepts one numeric value and emits one number; it is not a multi-thumb range\ncontrol. There is no defaultValue, orientation, tick-value, format, or value-label\nprop. Show a sibling text value when users need the precise current number.\n\nMarks are labels distributed along the control. Records do not accept position,\nvalue, color, or onClick fields. A mark named 50 does not itself place a tick at 50. Use a short set of endpoint/context labels consistent with the range.\n\n```dil\n{@body const [level,setLevel] = DIL.useState(40)}\n<label>Level</label>\n<slider aria-label="Level" min={0} max={100} step={5} value={level} onChange={setLevel} marks={[{label:"Low"},{label:"High"}]}/>\n<text tabularNums>{level}%</text>\n```\n\n#### Component: checkbox\n\n```text\nProperties:\n checked: boolean (optional; default false)\n disabled: boolean (optional; default false)\n lineThrough: boolean (optional; default true)\n onChange: callback (checked:boolean) => void (optional)\n\nChildren: inline\n```\n\nChildren provide the visible clickable label. Bind checked/onChange to state for\nreactive output. The callback receives boolean, not the underlying tri-state API\nor a DOM event. There is no indeterminate, value, defaultChecked, name, aria-label,\nor form-submission prop. Use a separate string field only when the task needs it.\n\nLineThrough controls the checked-label styling. Set it false for settings and\nconsent-style choices; the default suits checklist completion. The label\'s checked\nstyling uses the bound upstream checked value, while the control can show its\nimmediate draft during worker acknowledgement. Keep binding complete rather than\nusing local draft behavior as a state-management mechanism.\n\n#### Component: radio-group\n\n```text\nProperties:\n aria-label: string (optional in API; supply for generation)\n value: string (optional; default empty string)\n direction: "row" (optional; omitted gives vertical arrangement)\n onChange: callback (value:string) => void (optional)\n\nChildren: radio\n```\n\nUse for one choice among visible options. Bind value/onChange to state and give\neach radio a unique nonempty string value. Use direction="row" for a wrapping\nhorizontal group. A direction="column" prop is not an additional enum member;\nomit the prop for vertical. No authored disabled prop exists for the group or\nits radios. Runtime readiness may disable them while source is incomplete.\n\n#### Component: radio\n\n```text\nProperties:\n value: string (required for generation)\n\nChildren: inline\n```\n\nPlace directly under radio-group, possibly through each/if. Children supply the\nvisible label. Selection and callbacks belong to the group; radio has no checked,\nonChange, disabled, name, or layout props. Do not use a standalone radio outside\nits required group context.\n\n#### Composition: radio-group > radio\n\n```text\n<radio-group>\n children: radio\n <radio>\n children: inline\n```\n\n```dil\n{@body const [billing,setBilling] = DIL.useState("monthly")}\n<radio-group aria-label="Billing" value={billing} onChange={setBilling} direction="row">\n <radio value="monthly">Monthly</radio>\n <radio value="annual">Annual</radio>\n</radio-group>\n<text>Selected: {billing}</text>\n```\n\n#### Component: segmented-control\n\n```text\nProperties:\n aria-label: string (optional in API; supply for generation)\n value: string (optional; default empty string)\n options: {value:string,label:string}[] (required for generation)\n onChange: callback (value:string) => void (optional)\n\nChildren: none\n```\n\nUse a short array of distinct nonempty string values and readable labels. Bind\nvalue/onChange to state. The component emits the selected string, ignoring an\nempty deselection value. Keep the bound selection among options unless a deliberate\ninitial unselected state is required. It has no multi-select, disabled, option\nicons, per-option callbacks, or arbitrary child composition.\n\nSegmented-control selects a value; it is not an authored tabs/panel component.\nRender content for the selection using if directives. Do not invent tab-panel,\nonTabChange, or content props. For long choices, prefer radio-group with readable\nlabels rather than crowded segments.\n\n## 4. Specialized components\n\n### Data-linked components\n\nThere is no stock query, remote-data, subscription, provider, entity-card, or\nservice-connected component. The supported data-bearing visualization props are\nChart.content and NodeGraph.content. Their data shapes are specified under Charts.\nOrdinary text, tables, and repeated layouts can also display supplied records.\nNone of those components fetches facts based on its label or content keys.\n\nWhen the enclosing task supplies data, include the relevant records as literal\nvalues in a declaration. Keep only fields needed for the interface. Preserve\nstable IDs, units, and source labels. If the input is incomplete, show the known\nfields with an explicit unknown/empty condition rather than fabricating values.\nDo not infer a remote endpoint from a component name.\n\nSeparate facts from local interaction state. A const record is a good authoring\nrepresentation of read-only supplied facts; it is not a frozen JavaScript object\nor an enforced immutable data store. Treat it as read-only by instruction. Use\nuseState for a selected record, draft, filter, or local edit. Do not claim that\nchanging that state updates the original external system.\n\n#### Task: supplied-data-summary\n\n```dil\n{@body const records = [{id:"a",name:"Alpha",amount:12},{id:"b",name:"Beta",amount:18}]}\n{@body const [query,setQuery] = DIL.useState("")}\n{@body const visibleRecords = records.filter(item => item.name.toLowerCase().includes(query.toLowerCase()))}\n{@body const visibleTotal = visibleRecords.reduce((sum,item) => sum + item.amount,0)}\n<input aria-label="Filter records" value={query} onChange={setQuery}/>\n<text>{visibleRecords.length} records, {visibleTotal} sample units</text>\n{#if visibleRecords.length > 0}\n {#each visibleRecords as item}<text>{item.name}: {item.amount}</text>{/each}\n{:else}\n <caption>No matching records.</caption>\n{/if}\n```\n\nThe filter transforms supplied data locally. It does not make a search request.\nUse wording such as Filter records rather than Search the database when no database\noperation exists. Do not add a refresh button that merely redraws unchanged facts.\nA reset-filter button can be truthful because it changes local query state.\n\n### Links and citations\n\nNo stock anchor, citation, reference card, source lookup, footnote resolver, or\nURL-opening action is available. Markdown recognizes link syntax but displays the\nlabel as an inert text span. It does not preserve the URL as a clickable target.\nMarkdown images do not load. The renderer\'s safe behavior must not be described\nas browser navigation.\n\nWhen a source matters, include its supplied title and visible URL in ordinary text.\nKeep source numbering local and unambiguous if the input already provides it.\nDo not invent a bracketed token that implies a host citation registry. A string\nsuch as [1] is just text unless the surrounding application provides another\nexplicit contract. Source cards can be composed from box/title/caption, but they\nremain informational and do not gain privileged behavior.\n\n#### Task: source-attribution\n\n```dil\n<box border padding={3} gap={2}>\n <title>Supplied source</title>\n <text>Example release notes</text>\n <caption>https://example.com/releases</caption>\n <caption>Reference address shown as text.</caption>\n</box>\n```\n\nIf the user requests a navigable link, state the capability limit rather than\ninventing GenUI.openUrl or window.open. A copy button may copy the supplied URL\nunder the documented clipboard contract. Label that action Copy URL, not Open.\nDo not automatically copy a URL when displaying its source.\n\n### Embedded application blocks\n\nThere is no authored iframe, app, embed, script, external widget, plugin frame,\nbrowser page, or sandbox block. The renderer\'s own isolation frame is application\ninfrastructure, not a DIL component that generated source can configure. An\ninteractive dashboard built from supported components remains one DIL document.\n\nCodeBlock displays or locally edits source. It does not compile an app, install\ndependencies, execute a preview, create a file, or host a separate application.\nDo not present its editor as a working code runner. If the task needs a mock\napplication, implement its supported local interactions with state and components\nand label any unimplemented server behavior accurately.\n\nCustom components are available only under an explicit host-supplied authoring\ncontract. That contract must establish exact case-sensitive names, property types,\nchildren, callback arguments, data boundaries, and any host actions. A demo showing\na host component override is not an instruction to generate that component in\nanother document. Do not guess a custom component because the stock vocabulary\nlacks a desired feature.\n\nThe stock specification validator cannot establish arbitrary custom host semantics.\nIf a host contract exists, validate custom examples against that contract and the\nreal host integration. Keep the distinction visible in the generation instructions.\nWithout such a contract, use only stock components and state the unsupported part.\n\n## 5. Visualizations\n\n### Images\n\nUse AsyncImage under its Media components contract when a placeholder illustration\nfits the task. It cannot display a supplied photograph URL. Do not put a URL in\nquery and claim the result is the referenced image. Markdown image syntax is\nsuppressed; there is no stock img/src escape hatch.\n\nFor simple authored illustrations, use the presentation-only SVG vocabulary. Put\na text description next to the visual and keep important values available as text.\nSVG is useful for a small static schematic, not a replacement for accessible\ncontrols, arbitrary HTML, or a browser canvas application.\n\n#### Component: svg\n\n```text\nProperties:\n svg props\n\nChildren: SVG elements\n```\n\nShared SVG props:\n\n```text\nviewBox: string\nwidth: number | string\nheight: number | string\nx: number | string\ny: number | string\ncx: number | string\ncy: number | string\nr: number | string\nrx: number | string\nry: number | string\nd: string\nfill: string\nstroke: string\nstrokeWidth: number | string\nfontSize: number | string\nfontWeight: number | string\nopacity: number | string\nid: string\nmarkerWidth: number | string\nmarkerHeight: number | string\nrefX: number | string\nrefY: number | string\norient: string\nmarkerEnd: string\n```\n\nAll SVG props are optional at the reader boundary; choose the subset required for\nthe selected geometry. Give the root viewBox and practical dimensions so the\nimage is visible and bounded. Use a simple fill/stroke and finite coordinates.\nSVG strings do not use the DIL semantic-color translation; choose literal safe\npaint values such as #5e4cff, currentColor, or none where appropriate.\n\nAllowed SVG elements: svg, defs, marker, path, rect, circle, line, polyline,\npolygon, g, ellipse, text, tspan, linearGradient, stop. Their names are exact;\nlinearGradient is not linear-gradient. These descendants are recognized only in\nan SVG subtree. A text tag there is an SVG text element, not the DIL text component.\nDo not place DIL controls or layouts inside an SVG drawing.\n\nThe attribute allowlist is shared, not a complete per-element SVG schema. A prop\nbeing allowed does not mean it has meaning on every element. Use width/height for\nrect, cx/cy/r for circle, cx/cy/rx/ry for ellipse, and d for path. The allowlist\ndoes not expose x1/y1/x2/y2 or points; use path for explicit lines and polygons.\nEmpty line/polyline/polygon elements may parse and render without useful geometry.\n\nGradient and stop elements are recognized, but offset, stopColor, gradientUnits,\nx1/x2, and related full-SVG controls are not exposed. Do not promise an authored\nmulti-stop gradient with this restricted surface. Choose solid paint for reliable\nillustrations. The examples include these recognized elements to show the actual\nsupported vocabulary and its limits, not to invent the missing attributes.\n\nSVG values are filtered for dangerous/external strings. External http/data targets,\nJavaScript URLs, markup-like/declaration strings, and nonlocal URL references are\nnot accepted. Local references such as `url(#arrow)` are supported for paint or\nmarker use. Choose simple document-local IDs containing letters, digits, underscores,\nor hyphens. Avoid colliding IDs across several authored SVGs in one document.\n\nThere is no href, xlink:href, style, className, transform, event handler, aria-label,\nrole, foreignObject, script, image, a, animate, or arbitrary SVG element/prop API.\nDo not add them. An SVG element has no onClick bridge and cannot authorize a host\naction. Use a real button next to the drawing if the user needs an action.\n\n#### Composition: svg > defs > marker; svg > g > path + text\n\n```text\n<svg>\n children: SVG elements\n <defs>\n children: marker | linearGradient\n <marker>\n children: SVG shapes\n <linearGradient>\n children: stop\n <g>\n children: SVG shapes | g | text\n <text>\n children: text content | tspan\n```\n\nThe tree describes useful combinations for generation; it is not a claim that\nthe parser validates a complete SVG content model. Keep definitions in defs,\nshape groupings in g, and text spans inside text. Use nested tspan only for simple\ntext positioning supported by x/y; there is no dx/dy/textAnchor API.\n\n```dil\n<caption>Flow from Alpha to Beta.</caption>\n<svg viewBox="0 0 320 100" width="100%" height={100}>\n <defs>\n <marker id="flow-arrow" markerWidth={10} markerHeight={10} refX={8} refY={3} orient="auto">\n <path d="M0 0 L8 3 L0 6 Z" fill="#5e4cff"/>\n </marker>\n </defs>\n <g>\n <rect x={10} y={20} width={90} height={55} rx={8} fill="#eeeeff"/>\n <rect x={220} y={20} width={90} height={55} rx={8} fill="#eeeeff"/>\n <path d="M105 47 L210 47" stroke="#5e4cff" strokeWidth={2} markerEnd="url(#flow-arrow)"/>\n <text x={25} y={52} fontSize={16} fill="#252838">Alpha</text>\n <text x={235} y={52} fontSize={16} fill="#252838">Beta</text>\n </g>\n</svg>\n```\n\n### Charts\n\nUse Chart for quantitative plots, NodeGraph for selectable service-style node\ndiagrams, and Mermaid for declarative diagram text. They have separate contracts;\ndo not combine their content formats. Each is a leaf component. Place a nearby\ntitle, units, and summary in normal layout siblings.\n\n#### Component: Chart\n\n```text\nProperties:\n content: object (required for generation)\n\nChildren: none\n```\n\nLine/bar/scatter content:\n\n```text\n{\n chartType: "line" | "bar" | "scatter",\n data: object[],\n xKey: string,\n series: {dataKey:string,label?:string}[]\n}\n```\n\nPie content:\n\n```text\n{\n chartType: "pie",\n data: object[],\n nameKey: string,\n valueKey: string\n}\n```\n\nSupply chartType explicitly. An absent or unrecognized type currently follows\nthe line rendering branch, but that fallback is not an invitation to generate\nother names. Only line, bar, scatter, and pie are supported chart types. Do not\nemit area, radar, bubble, candlestick, heatmap, or composed-chart components.\n\nData is an array of plain records. For line/bar, xKey identifies a category or\nnumeric x field; each series dataKey identifies a finite numeric y field. Label\nis optional and falls back to dataKey. Keep field keys and series keys stable and\ndistinct. Supply units in nearby text rather than inventing axis-formatting props.\nDo not place React components, functions, or expression strings inside content.\n\nScatter uses numeric x data and the first series\' dataKey for the shared numeric\ny-axis configuration. Use one series for the clearest contract. If several series\nare used, keep numeric fields and units compatible; there is no per-series axis\nor arbitrary domain configuration. Line/bar may display several series from the\nsame data rows. Missing numeric values are not a defined missing-data policy;\npreprocess supplied data deliberately and explain unknown values in text.\n\nPie uses nameKey for labels and valueKey for quantitative slices. Prefer unique\nnonempty string names and nonnegative finite values with a positive total. It\nrenders a ring-style pie using stock radii. There is no innerRadius, label\nformatter, custom sector, selectedSlice, or click callback API.\n\nStock chart dimensions, palette, axes, tooltip, marks, and legend are internal.\nNo DIL width/height/layout, color, onSelect, onClick, tooltip, axis, domain, or\nlegend prop is exposed. A wrapper can constrain available width but cannot set a\nnew chart-content schema. Do not infer the full Recharts API from the underlying\nimplementation.\n\nMulti-series line/bar legends support internal visibility selection. This widget\nstate is not exposed as a DIL binding and does not invoke an authored callback.\nScatter and pie legends do not offer the same multi-series selection contract.\nHover/focus emphasis is presentation behavior, not data selection available to\nother document components.\n\n#### Task: line-chart\n\n```dil\n<title>Sample trend</title>\n<Chart content={{chartType:"line",data:[{month:"Jan",actual:10,plan:12},{month:"Feb",actual:15,plan:14}],xKey:"month",series:[{dataKey:"actual",label:"Actual"},{dataKey:"plan",label:"Plan"}]}}/>\n<caption>Synthetic units. Actual rises from 10 to 15.</caption>\n```\n\n#### Task: pie-chart\n\n```dil\n<Chart content={{chartType:"pie",data:[{name:"Alpha",amount:30},{name:"Beta",amount:70}],nameKey:"name",valueKey:"amount"}}/>\n<caption>Synthetic shares: Alpha 30%, Beta 70%.</caption>\n```\n\nWhen chart data is empty, show an explicit empty-state caption instead of claiming\nthe absence of marks means a zero result. Use a small textual table when values\nmatter more than the visual. Do not fabricate enough points to make a supplied\ndataset appear more complete. If a transformation drops records, explain why.\n\n#### Component: NodeGraph\n\n```text\nProperties:\n content: object (required for generation)\n selectedId: string (optional; no selected node when omitted)\n onSelect: callback (id:string) => void (optional)\n\nChildren: none\n```\n\nContent:\n\n```text\n{\n nodes: {id:string,label:string,sub?:string,x?:number,y?:number}[],\n edges: {id?:string,source:string,target:string,label?:string}[]\n}\n```\n\nUse unique nonempty string node IDs. Label is the main node text and sub is an\noptional secondary line. x/y are optional finite positioning hints. Without\npositions, nodes are arranged in a simple multi-column layout. The renderer\nadjusts columns and vertical placement to keep nodes readable, so positions are\nnot a pixel-exact canvas contract.\n\nEdges refer to existing node IDs by source and target. Give edges stable IDs when\nsupplied; otherwise the renderer uses positional IDs. Invalid endpoints are\nfiltered. Only the first 200 nodes and first 400 edges are considered; an edge\nto a truncated node will not appear. Keep author output within the limits and\nsummarize oversized supplied networks rather than silently claiming full coverage.\n\nSelectedId controls visible node selection. OnSelect receives the clicked node\'s\nstring ID. Bind the pair to state if selection should update another panel or\nremain visibly selected. Without that binding, a callback alone does not update\nthe selectedId prop. There is no selected-node record argument or DOM event.\n\nNode dragging and connection creation are disabled. Pan/zoom controls are built\nin; no DIL camera, zoom, connect, drag, edge click, node style, node type, handle,\nor custom action prop exists. Treat the graph as a navigable selection display,\nnot an editable diagramming application. State changes must use supported callbacks.\n\n```dil\n{@body const [selectedId,setSelectedId] = DIL.useState("api")}\n{@body const graph = {nodes:[{id:"api",label:"API",sub:"Entry"},{id:"db",label:"Database",sub:"Storage"}],edges:[{id:"api-db",source:"api",target:"db",label:"reads"}]}}\n<NodeGraph content={graph} selectedId={selectedId} onSelect={setSelectedId}/>\n<text>Selected service: {selectedId}</text>\n```\n\n#### Component: Mermaid\n\n```text\nProperties:\n source: string (required for generation)\n\nChildren: none\n```\n\nPass Mermaid diagram text as a string expression. A fenced mermaid block is an\nalternative Markdown representation using the same diagram renderer. Do not put\nraw children between Mermaid tags; the component reads its source prop only.\nUse a simple flowchart or another valid Mermaid diagram syntax without app-level\nconfiguration.\n\nThe renderer uses strict security, neutral theme, no HTML labels, maximum text\nsize 8,192 characters, and maximum 100 edges. Authored configuration directives,\nfrontmatter at the start, classDef, style/linkStyle lines, click actions, and\nHTML-like source are rejected. Output is sanitized to remove unsafe SVG content,\nincluding links, scripts, and foreignObject. Do not depend on a sanitized link to\nbecome navigable.\n\nInvalid or incomplete source can display a diagram error. Keep Mermaid source\nsmall and syntactically complete. There is no authored callback, theme, config,\ndownload, source editor, or node-selection API. Use NodeGraph if the task requires\nsupported selection state rather than attempting Mermaid click handlers.\n\n```dil\n<Mermaid source={"flowchart LR\\n Request --> Review\\n Review --> Ready"}/>\n```\n\n### Maps\n\nNo map component, map adapter, tiles, geocoder, geographic marker, route engine,\nor map selection callback exists. Do not emit Map, GeoMap, map, marker, or arbitrary\nHTML embeds. A node graph is not a geographic coordinate system. SVG can show a\nsmall authored schematic, but that does not establish a map-data integration.\n\nPresent supplied places as text, a table, or local filtering over records. Preserve\ngiven coordinates as values rather than inventing geocoding results. If location\nnames lack coordinates, do not claim a computed distance or route. Show the\ncapability limit when an interactive map is central to the request.\n\n#### Task: location-table\n\n```dil\n{@body const places = [{id:"berlin",name:"Berlin",latitude:52.52,longitude:13.405}]}\n<title>Supplied locations</title>\n<table>\n {#each places as place}\n <table-row>\n <table-cell>{place.name}</table-cell>\n <table-cell>{place.latitude}, {place.longitude}</table-cell>\n </table-row>\n {/each}\n</table>\n<caption>Coordinates are shown as supplied; no map or geocoding service is connected.</caption>\n```\n\n## 6. Interactivity\n\n### State management\n\nOnly `DIL.useState(initialValue)` is supported. It is recognized by the declaration\nsyntax and does not expose the React hook object. Use one unique state pair per\ndeclaration. A lazy initializer runs when that state name is first initialized.\nDo not call hooks in interpolation, handler bodies, derived const expressions,\nconditional branches, or repeated templates.\n\nSetters accept a replacement value or a function mapping previous state to next\nstate. Use an updater whenever a new value depends on the previous value and\nseveral actions may be queued. Keep the updater pure. It may build a new array\nor object using ordinary JavaScript expressions; do not mutate previous state.\n\n```dil\n{@body const [count,setCount] = DIL.useState(0)}\n<row gap={2} align="center">\n <button onClick={() => setCount(previous => previous + 1)}>Increment</button>\n <button variant="outline" onClick={() => setCount(0)}>Reset</button>\n <text tabularNums>{count}</text>\n</row>\n```\n\nReplace arrays with map/filter/spread and replace changed records with object\nspread. Mutation such as items.push, record.done=true, or sort in place does not\nestablish the intended setter/dependency contract. Use a copied array before sort.\nKeep source facts separate from editable state so an agent can tell which values\nare user drafts.\n\nState is document-owned. It persists across appends, conditional visibility, and\nvirtualized presentation within that document. A new message/document identity or\nreplacement can reset it. There is no storage or cross-message state API. Do not\npromise reload persistence, multi-user synchronization, browser-tab sharing, or\nserver write-back.\n\nRepeated source shares top-level state. Represent per-record edits with an array\nof records or an object keyed by stable ID. Never create a body declaration inside\neach expecting an independent state instance. Use the repeated item ID in the\nhandler\'s immutable update instead.\n\n#### Task: repeated-record-state\n\n```dil\n{@body const [tasks,setTasks] = DIL.useState([{id:"a",label:"Review Alpha",done:false},{id:"b",label:"Review Beta",done:false}])}\n{@body const completeCount = tasks.filter(task => task.done).length}\n<text>{completeCount} of {tasks.length} complete</text>\n{#each tasks as task}\n <checkbox checked={task.done} onChange={checked => setTasks(previous => previous.map(entry => entry.id === task.id ? {...entry,done:checked} : entry))}>\n {task.label}\n </checkbox>\n{/each}\n```\n\nOrdinary const getters are sufficient for derived count, totals, filtered arrays,\nvalidity, and selected-record lookup. They are not a caching API. Do not generate\nuseMemo or useCallback to optimize a DIL document. Keep expensive transformations\nsmall and reuse a readable binding when it improves correctness.\n\nWidget-local state has a different contract. Input/slider/checkbox keep immediate\ndrafts while worker callbacks complete. CodeBlock retains editable source drafts.\nChart legends hold visibility internally. Popover/carousel maintain their own\ninteraction state. Only documented bindings expose values back to authored DIL.\nDo not try to read internal widget state through refs, DOM, hidden props, or globals.\n\n### Event callbacks\n\nCallback values may be setter references, derived function bindings, or function\nexpressions. Pass the function; do not invoke it while assigning the prop. For\nexample, onChange={setName} is a callback, while onChange={setName("Ada")} performs\nwork during evaluation and does not supply a valid handler.\n\n#### Callback: button.onClick and pressable.onClick\n\nSignature: `() => void`. Ignore the undefined argument supplied by the generic\ninvocation path. There is no MouseEvent, target, currentTarget, preventDefault,\nstopPropagation, or coordinates. Use captured declared values to determine the\naction. A user activation on these supported action controls can authorize a\nsynchronous GenUI.copy request; arbitrary callbacks do not gain that authority.\n\n#### Callback: input.onChange\n\nSignature: `(value:string) => void`. Receive the complete current input string.\nUse a setter directly for simple controlled input. For a transform, use a function\nthat calls the setter with the transformed value. Keep the value prop a string.\nDo not read event.target.value or depend on an input-type conversion API.\n\n#### Callback: slider.onChange\n\nSignature: `(value:number) => void`. Receive the scalar numeric value, not an array\nof thumb values or a browser event. Bind the number directly and derive formatted\ntext separately. Do not put a clipboard request in this handler; slider changes\nare not privileged action-control activations.\n\n#### Callback: checkbox.onChange\n\nSignature: `(checked:boolean) => void`. Receive true or false. The underlying UI\nlibrary\'s indeterminate representation is normalized; it is not exposed as a DIL\nvalue. Bind checked to boolean state. Keep the callback about changing local choice\nstate, and use a separate action button for copying or other explicitly supported\nprivileged work.\n\n#### Callback: radio-group.onChange and segmented-control.onChange\n\nSignature: `(value:string) => void`. Receive the selected option\'s value, not its\nlabel or a record. Resolve a record with a derived lookup if the UI needs more\nfields. Selection does not submit a form. Segmented-control ignores an empty\ndeselection value; do not use empty option strings as ordinary choices.\n\n#### Callback: NodeGraph.onSelect\n\nSignature: `(id:string) => void`. Receive the node ID. Bind selectedId to state\nand derive the selected node from content.nodes if needed. There is no graph\nevent object, coordinates, edge ID, or selection array. Selection callbacks do\nnot authorize clipboard requests.\n\nKeep callback bodies synchronous and bounded. A callback can update several local\nstate values in order, but it is not a lifecycle effect or an asynchronous task\nrunner. Do not depend on a Promise return value, timer, network response, or host\ncallback completion. State setters have no success receipt available to authored\nsource. Derive updated UI from state, not from guessed render timing.\n\nControl readiness is managed by the runtime. Open/incomplete source, unresolved\nexpressions, or a stopped document can make controls temporarily unavailable.\nDo not add a fake loading hook or artificial timer to work around that state.\nGenerate complete source and let the existing renderer manage readiness.\n\nThere are no onSubmit, onInput, onBlur, onFocus, onKeyDown, onLoad, onError,\nonOpenChange, onValueChange, onDrag, or arbitrary DOM callbacks in the author API.\nDo not copy underlying React primitive names into DIL. Use the event names listed\nhere, including the capitalized NodeGraph component name.\n\n#### Task: validation-form\n\nThere is no form tag or browser validation contract. Compose a field, derived\nvalidity, visible error text, and guarded action. A disabled button is useful\nfeedback; a handler guard ensures the action itself also checks validity.\n\n```dil\n{@body const [name,setName] = DIL.useState("")}\n{@body const trimmedName = name.trim()}\n{@body const valid = trimmedName.length >= 2 && trimmedName.length <= 80}\n<box gap={3} maxWidth={420}>\n <label>Name</label>\n <input aria-label="Name" value={name} onChange={setName} placeholder="At least two characters"/>\n {#if !valid}<caption color="danger">Enter a name between 2 and 80 characters.</caption>{/if}\n <button disabled={!valid} onClick={() => { if (valid) GenUI.copy(trimmedName); }}>Copy name</button>\n</box>\n```\n\nThis copies a valid local draft. It does not submit, save, create a user, or email\nanyone. If the requested outcome requires an absent host action, state that limit\nand do not substitute a misleading success message. Do not call the copy result\na successful form submission.\n\n### Data bindings\n\nThere is no predefined external-data variable, provider registry, props object,\ncontext hook, request result, subscription, or remote mutation API. Embed supplied\nJSON-compatible records in a top-level const declaration. A host can supply a\nseparate custom contract, but stock generated source must not guess one.\n\nRead fields with dot access, optional chaining, and computed keys. Use pure array\nand string operations to transform data for display. Computed property names are\nsupported JavaScript expressions, not a remote query language. Only access fields\npresent in the supplied data or created by the document. Use explicit null/empty\nchecks when the input permits absent values.\n\nUse const bindings as read-only source facts by instruction. This is not an\nenforced Object.freeze guarantee. Use state for drafts and preserve source IDs.\nDo not change source data in place to imitate a two-way binding. A state change\nupdates dependent expressions; it does not write back to an external origin.\n\nBinding scope:\n\n| Binding | Visible where | Lifetime |\n| --------------------- | ----------------------------------------------------------- | --------------------------- |\n| Top-level const/state | Same document\'s expressions and callbacks | Mounted document |\n| each item/index | Rendered subtree of that iteration, including nested scopes | Corresponding item instance |\n| Callback parameter | Its function body | Callback invocation |\n| Code editor draft | Internal CodeBlock only | Document draft identity |\n| Chart legend state | Internal Chart only | Widget presentation state |\n\nA body declaration is always document-scoped and never captures a loop binding.\nAn event function expression inside a repeated rendered subtree can capture its\nitem/index scope. Use the stable item ID in updates rather than a potentially\nstale position. Keep source declarations outside the repeated template.\n\n```dil\n{@body const supplied = [{id:"a",name:"Alpha",amount:12},{id:"b",name:"Beta",amount:18}]}\n{@body const [selected,setSelected] = DIL.useState("a")}\n{@body const current = supplied.find(item => item.id === selected)}\n{#each supplied as item}\n <button variant="outline" onClick={() => setSelected(item.id)}>{item.name}</button>\n{/each}\n{#if current}<text>{current["name"]}: {current.amount}</text>{:else}<caption>No selection.</caption>{/if}\n```\n\nUse the same principle for chart data: derive a plain content object or use bound\narrays within content. The chart does not subscribe to the originating dataset;\nit re-renders from the supplied prop. An empty array is an empty dataset, not a\nloading indication. Loading and failed-request states require explicit supplied\nfacts or a separate host contract; do not fabricate asynchronous phases.\n\n### Host actions\n\nOnly `GenUI.copy(text:string): undefined` is exposed. It requests a clipboard\nwrite of at most 65,536 characters. It does not read the clipboard or create a\nfile. Pass an actual string; serialize records deliberately if the requested\ntask is to copy JSON. A nonempty request is required for a dispatched copy;\nempty text currently produces no clipboard operation.\n\nInvoke copy synchronously in a button or pressable onClick after explicit user\nactivation. The renderer carries an action intent through the host boundary and\nassociates the clipboard outcome with that initiating control. A valid-looking\ncall in initialization, interpolation, a getter, a value-change handler, or a\nnode-selection callback cannot confer the required authorization.\n\nDo not defer copy through Promise.then, async/await, timers, or an automatic\neffect. Those are not documented action paths. Do not forge internal receipt or\ngesture fields. Copy authorization and browser/platform permission are separate:\nthe platform can deny a correctly invoked request.\n\n```dil\n{@body const report = "Review complete: Alpha and Beta checked."}\n<button onClick={() => GenUI.copy(report)}><icon name="copy"/> Copy report</button>\n```\n\nCall once per action. The VM tracks one copy value for an execution; several copy\ncalls do not establish an ordered batch of clipboard writes. Keep the requested\npayload below the limit and construct it before invocation with a pure binding.\nIf copying a selected record, validate that selection exists in the handler.\n\nThe call returns undefined. It is not a Promise and does not return success or\nfailure to authored source. Do not branch on its return value or set copied=true\nimmediately after calling it. Button/pressable display Copied or Copy failed using\nthe actual host outcome. CodeBlock\'s built-in copy control has its own feedback.\nUse that behavior rather than duplicate success flags or guessed timeouts.\n\nClipboard denial should leave the existing content and local draft available.\nUsers can retry the same explicit action after resolving platform permissions.\nDo not clear the input merely because copy was requested. Do not promise a\nclipboard read-back or automatic retry; neither is an author API.\n\nUnsupported host operations include openUrl, issueNewTurn, download, export,\nfile creation, printing, network requests, storage, browser navigation, arbitrary\npostMessage, and server mutations. Mention an unavailable capability when it is\nessential to the requested task. Never replace it with an invented GenUI method.\nThe renderer\'s own transport and widget-internal browser calls are not privileges\ngranted to authored expressions.\n\n#### Task: host-action-review\n\nCheck the control, event, payload type, payload length, and execution timing.\nA copy button with a string payload and synchronous onClick is supported. A\nslider onChange that calls copy, a const getter that calls copy while rendering,\nor an automatic initialization call is unsupported even if the text is harmless.\nKeep copy requests intentional and visible to the person activating the control.\n\n## 7. Assets\n\n### Icons\n\n#### Component: icon\n\n```text\nProperties:\n name: string (required for generation)\n size: "xs" | "lg" (optional; default 17px)\n color: string (optional)\n\nChildren: none\n```\n\nSupported names:\n\n```text\nchart-no-axes-combined\ncircle-check\ncheck-circle-2\ncircle\nwallet\ntrending-up\nusers\nrotate-ccw\ncopy\nsliders-horizontal\nellipsis\nsparkles\nmouse-pointer-click\nx\ngit-merge\npackage-check\nshield-check\nsettings-2\ninfo\ncode-2\nalert-triangle\n```\n\nUse exactly these names. An unknown name falls back to circle, which can conceal\na generation mistake rather than raise an error. Do not request an external\nLucide name because the renderer internally uses Lucide. The allowlist is the\nauthor API. There is no arbitrary SVG path, icon URL, upload, sprite, or library\nimport prop.\n\nSize xs=13px, omitted=17px, lg=22px. There is no explicit md size enum; omit size\nfor the normal icon. Color uses the same semantic token/CSS color reader as DIL\ntext. It does not accept a CSS class, style object, or custom variable. Icons are\ninline decorative elements; put them beside meaningful text.\n\nIcons are aria-hidden in the stock renderer. They cannot carry an authored\naria-label or title prop. An icon-only button needs its own aria-label. A badge\nor status line needs visible words even when its icon seems recognizable. Do not\ncommunicate critical state using icon shape/color alone.\n\n#### Composition: button > icon + inline text\n\n```dil\n<button onClick={() => GenUI.copy("Review complete")}>\n <icon name="copy" size="xs"/> Copy review\n</button>\n```\n\n#### Composition: button > icon with accessible action name\n\n```dil\n{@body const [count,setCount] = DIL.useState(0)}\n<button aria-label="Reset count" variant="ghost" onClick={() => setCount(0)}>\n <icon name="rotate-ccw"/>\n</button>\n<text>{count}</text>\n```\n\nUse the example catalog\'s icon gallery to locate all allowed names. Icons do not\ncreate host operations: a download-looking symbol would not add a download API,\nand the copy icon itself has no onClick. Put the supported action on the containing\nbutton or pressable and obey the host-action contract.\n';
4
+ var agentSpecExamples = '# GenUI Examples\n\nSearch `Component: slider`, `Composition: table`, `SVG element: path`, or\n`Task: controlled-counter`. Every `dil` fence is an independent complete document.\nDo not concatenate examples without renaming their document-wide declarations.\nData is synthetic unless a recipe explicitly describes supplied records.\n\nLookup index:\n\n- Text: text, title, caption, badge, label, CodeBlock.\n- Media: AsyncImage.\n- Layout: box, row, grid, grid-item, spacer, divider, table, table-row,\n table-cell, popover, popover-trigger, popover-content, carousel, carousel-item.\n- Inputs: button, pressable, input, slider, checkbox, radio-group, radio,\n segmented-control.\n- Visualizations: svg, Chart, NodeGraph, Mermaid; every allowed SVG descendant.\n- Assets: icon and the complete supported-name gallery.\n- Compositions: grid, table, popover, carousel, radio-group, SVG definitions,\n inline icons, nested layouts, conditional/repeated named children.\n- Tasks: static-card, controlled-counter, conditional-status, dynamic-list,\n validation-form, host-action, external-data, incomplete-stream.\n\n## 1. Output format and safety\n\n#### Task: static-card\n\nGenerate source directly. This fence is for lookup and verification; a generated\nUI response normally omits the surrounding fence.\n\n```dil\n<box border padding={4} radius="xl" gap={3} maxWidth={480}>\n <title>Release review</title>\n <text>Prepared for review.</text>\n <badge color="success"><icon name="circle-check"/> Ready</badge>\n</box>\n```\n\n## 2. Syntax and parsing\n\n### Markdown\n\n#### Syntax: markdown-prose\n\n```dil\n# Review notes\n\n**Two records** are ready. Values below are synthetic.\n\n- Alpha: 12 units\n- Beta: 18 units\n\n| Record | Units |\n| --- | --- |\n| Alpha | 12 |\n| Beta | 18 |\n\n> Verify the source before making a decision.\n```\n\n#### Syntax: literal-code\n\nCodeBlock, fenced code, and inline code spans protect braces and tags from DIL\nparsing.\n\n```dil\n<CodeBlock language="text">\n{literal braces}\n<unsupported-example>This is displayed source.</unsupported-example>\n</CodeBlock>\n<text>A literal opening brace: {"{"}</text>\n\nPass `{ leading: false }` to `debounce`, and wrap the chart in a `<div>`.\n```\n\n### JavaScript expressions\n\n#### Syntax: expressions-and-attributes\n\n```dil\n{@body const item = {name:"Alpha",amount:12}}\n{@body const field = "name"}\n<box border padding={{x:4,y:3}}>\n <text>{item[field]}: {item.amount * 2}</text>\n <caption>{`Original amount: ${item.amount.toFixed(1)}`}</caption>\n</box>\n```\n\n### State declarations\n\n#### Task: controlled-counter\n\nClick Increment to update both the number and status. Reset restores zero.\n\n```dil\n{@body const [count,setCount] = DIL.useState(0)}\n{@body const increment = () => setCount(previous => previous + 1)}\n<row gap={2} align="center" wrap="wrap">\n <button onClick={increment}>Increment</button>\n <button variant="outline" onClick={() => setCount(0)}>Reset</button>\n <text tabularNums>Count: {count}</text>\n</row>\n{#if count > 0}<badge color="success">Started</badge>{:else}<caption>Waiting</caption>{/if}\n```\n\n### Conditional rendering\n\n#### Task: conditional-status\n\n```dil\n{@body const [status,setStatus] = DIL.useState("waiting")}\n<segmented-control aria-label="Status" value={status} onChange={setStatus} options={[{value:"waiting",label:"Waiting"},{value:"ready",label:"Ready"},{value:"blocked",label:"Blocked"}]}/>\n{#if status === "ready"}\n <badge color="success">Ready</badge>\n{:else if status === "blocked"}\n <badge color="danger">Blocked</badge>\n{:else}\n <caption>Waiting</caption>\n{/if}\n```\n\n#### Task: dynamic-list\n\nIDs remain unique after removal and addition. Counter-based IDs are separate\nfrom the current array length.\n\n```dil\n{@body const [items,setItems] = DIL.useState([{id:"item-1",name:"Item 1"}])}\n{@body const [nextId,setNextId] = DIL.useState(2)}\n<button onClick={() => { setItems(previous => [...previous,{id:`item-${nextId}`,name:`Item ${nextId}`}]); setNextId(previous => previous + 1); }}>Add item</button>\n{#if items.length === 0}<caption>No items.</caption>{/if}\n{#each items as item,index}\n <row gap={2} align="center">\n <text>{index + 1}. {item.name}</text>\n <button variant="ghost" onClick={() => setItems(previous => previous.filter(entry => entry.id !== item.id))}>Remove {item.name}</button>\n </row>\n{/each}\n```\n\n#### Syntax: nested-each-scopes\n\n```dil\n{@body const groups = [{id:"review",name:"Review",items:[{id:"alpha",name:"Alpha"},{id:"beta",name:"Beta"}]}]}\n{#each groups as group}\n <box border padding={3} gap={2}>\n <title>{group.name}</title>\n {#each group.items as item,index}<text>{group.name}: {index + 1}. {item.name}</text>{/each}\n </box>\n{/each}\n```\n\n#### Task: incomplete-stream\n\nSend the following unfinished prefix without signalling completion:\n\n```text\n<box padding={\n```\n\nAppend `4}><text>Ready</text></box>`. Complete only after the combined document is:\n\n```dil\n<box padding={4}><text>Ready</text></box>\n```\n\n#### Syntax: streaming-repeat\n\nThe repeat waits for its closing directive. A first chunk can end here:\n\n```text\n{#each [{id:"a",name:"Alpha"}] as item}<text>{item.name}</text>\n```\n\nAppend `{/each}` to finish this executable source:\n\n```dil\n{#each [{id:"a",name:"Alpha"}] as item}<text>{item.name}</text>{/each}\n```\n\n## 3. Component API\n\n### Text components\n\n#### Component: text\n\n```dil\n<text color="primary" size="lg" weight="medium" tabularNums>1,234 units</text>\n```\n\n#### Component: title\n\n```dil\n<title size="xl">Quarterly review</title>\n```\n\n#### Component: caption\n\n```dil\n<caption color="secondary">Synthetic values, shown in units.</caption>\n```\n\n#### Component: badge\n\n```dil\n<badge color="warning"><icon name="alert-triangle" size="xs"/> Needs review</badge>\n```\n\n#### Component: label\n\nThe sibling input names itself explicitly; label has no association prop.\n\n```dil\n{@body const [name,setName] = DIL.useState("")}\n<label>Name</label>\n<input aria-label="Name" value={name} onChange={setName}/>\n```\n\n#### Component: CodeBlock\n\nEditing changes this widget\'s draft only. It does not execute the source or\nupdate an authored state binding.\n\n```dil\n<CodeBlock language="javascript" editable>\nconst message = "Hello";\nconsole.log(message);\n</CodeBlock>\n```\n\n### Media components\n\n#### Component: AsyncImage\n\n```dil\n<box maxWidth={480}>\n <AsyncImage query="Placeholder mountain landscape"/>\n <caption>Offline illustration, not a photograph.</caption>\n</box>\n```\n\n### Layout components\n\n#### Component: box\n\n```dil\n<box border={{size:1,color:"subtle"}} padding={{x:4,y:3}} radius="xl" background="surface-secondary" gap={2} maxWidth={480}>\n <title>Review panel</title><text>Two records are ready.</text>\n</box>\n```\n\n#### Component: row\n\n```dil\n<row gap={2} align="center" justify="between" wrap="wrap">\n <text>Release status</text><badge color="success">Ready</badge>\n</row>\n```\n\n#### Component: grid\n\n```dil\n<grid columns={2} gap={3}>\n <box border padding={3}><title>Alpha</title><text>12 units</text></box>\n <box border padding={3}><title>Beta</title><text>18 units</text></box>\n</grid>\n```\n\n#### Component: grid-item\n\n#### Composition: grid > grid-item\n\n```dil\n<grid columns={2} gap={3}>\n <grid-item border padding={3} radius="lg"><title>Alpha</title></grid-item>\n <grid-item border padding={3} radius="lg"><title>Beta</title></grid-item>\n</grid>\n```\n\n#### Component: spacer\n\n```dil\n<row gap={2} align="center"><title>Review</title><spacer/><badge>Prepared</badge></row>\n```\n\n#### Component: divider\n\n```dil\n<box gap={3}><text>Overview</text><divider/><text>Details</text></box>\n```\n\n#### Component: table\n\n#### Composition: table > table-row > table-cell\n\n```dil\n<table>\n <table-row><table-cell><text weight="medium">Name</text></table-cell><table-cell><text weight="medium">Units</text></table-cell></table-row>\n <table-row><table-cell>Alpha</table-cell><table-cell>12</table-cell></table-row>\n</table>\n```\n\n#### Component: table-row\n\n#### Composition: table > each > table-row\n\n```dil\n{@body const records = [{id:"a",name:"Alpha",amount:12},{id:"b",name:"Beta",amount:18}]}\n<table>\n {#each records as item}<table-row><table-cell>{item.name}</table-cell><table-cell>{item.amount}</table-cell></table-row>{/each}\n</table>\n```\n\n#### Component: table-cell\n\n#### Composition: table-cell > generic content\n\n```dil\n<table>\n <table-row>\n <table-cell padding={3}><row gap={2} align="center"><icon name="package-check"/><text>Alpha</text></row></table-cell>\n <table-cell><badge color="success">Ready</badge></table-cell>\n </table-row>\n</table>\n```\n\n#### Component: popover\n\n#### Composition: popover > popover-trigger + popover-content\n\n```dil\n<popover>\n <popover-trigger><button variant="outline">Details</button></popover-trigger>\n <popover-content><text>Additional review notes.</text></popover-content>\n</popover>\n```\n\n#### Component: popover-trigger\n\n#### Composition: popover-trigger > button\n\n```dil\n<popover>\n <popover-trigger><button aria-label="Review details" variant="ghost"><icon name="info"/></button></popover-trigger>\n <popover-content><caption>No additional action required.</caption></popover-content>\n</popover>\n```\n\n#### Component: popover-content\n\n#### Composition: popover-content > generic content\n\n```dil\n{@body const [showNotes,setShowNotes] = DIL.useState(true)}\n<popover>\n <popover-trigger><button variant="outline">Display options</button></popover-trigger>\n <popover-content side="top" align="end">\n <box gap={2}>\n <checkbox checked={showNotes} onChange={setShowNotes} lineThrough={false}>Show notes</checkbox>\n <caption>Selection: {showNotes ? "shown" : "hidden"}</caption>\n </box>\n </popover-content>\n</popover>\n{#if showNotes}<text>Review notes are visible.</text>{/if}\n```\n\n#### Component: carousel\n\n#### Composition: carousel > carousel-item\n\n```dil\n<carousel>\n <carousel-item><box border padding={4}><title>Alpha</title><text>First option.</text></box></carousel-item>\n <carousel-item><box border padding={4}><title>Beta</title><text>Second option.</text></box></carousel-item>\n</carousel>\n```\n\n#### Component: carousel-item\n\n#### Composition: carousel > each > carousel-item\n\n```dil\n{@body const cards = [{id:"a",title:"Alpha"},{id:"b",title:"Beta"}]}\n<carousel>\n {#each cards as card}<carousel-item><box border padding={4}><title>{card.title}</title></box></carousel-item>{/each}\n</carousel>\n```\n\n#### Composition: box > grid > grid-item > row\n\n```dil\n<box gap={3}>\n <title>Sample overview</title>\n <grid columns={2} gap={3}>\n <grid-item border padding={3} radius="lg"><row gap={2} align="center"><icon name="wallet"/><text>12 units</text></row></grid-item>\n <grid-item border padding={3} radius="lg"><row gap={2} align="center"><icon name="users"/><text>3 reviewers</text></row></grid-item>\n </grid>\n</box>\n```\n\n#### Composition: table > if > table-row\n\n```dil\n{@body const [showExtra,setShowExtra] = DIL.useState(false)}\n<checkbox checked={showExtra} onChange={setShowExtra} lineThrough={false}>Show extra row</checkbox>\n<table>\n <table-row><table-cell>Alpha</table-cell><table-cell>12</table-cell></table-row>\n {#if showExtra}<table-row><table-cell>Beta</table-cell><table-cell>18</table-cell></table-row>{/if}\n</table>\n```\n\n### Input components\n\n#### Component: button\n\n```dil\n{@body const [count,setCount] = DIL.useState(0)}\n<button variant="outline" size="sm" onClick={() => setCount(previous => previous + 1)}>Add one</button>\n<text>Count: {count}</text>\n```\n\n#### Component: pressable\n\n#### Composition: pressable > noninteractive generic content\n\n```dil\n{@body const [selected,setSelected] = DIL.useState(false)}\n<pressable border padding={4} radius="xl" gap={2} onClick={() => setSelected(previous => !previous)}>\n <title>Alpha option</title><text>Select this local option.</text>\n <badge>{selected ? "Selected" : "Not selected"}</badge>\n</pressable>\n```\n\n#### Component: input\n\n```dil\n{@body const [name,setName] = DIL.useState("")}\n<input aria-label="Display name" placeholder="Your name" value={name} onChange={setName}/>\n<text>Hello, {name.trim() || "reader"}.</text>\n```\n\n#### Component: slider\n\n```dil\n{@body const [level,setLevel] = DIL.useState(40)}\n<slider aria-label="Level" min={0} max={100} step={5} value={level} onChange={setLevel} marks={[{label:"Low"},{label:"High"}]}/>\n<text tabularNums>Level: {level}%</text>\n```\n\n#### Component: checkbox\n\n```dil\n{@body const [done,setDone] = DIL.useState(false)}\n<checkbox checked={done} onChange={setDone}>Review Alpha</checkbox>\n<caption>{done ? "Review complete" : "Review pending"}</caption>\n```\n\n#### Component: radio-group\n\n#### Composition: radio-group > radio\n\n```dil\n{@body const [billing,setBilling] = DIL.useState("monthly")}\n<radio-group aria-label="Billing" value={billing} onChange={setBilling} direction="row">\n <radio value="monthly">Monthly</radio><radio value="annual">Annual</radio>\n</radio-group>\n<text>Billing: {billing}</text>\n```\n\n#### Component: radio\n\n#### Composition: radio-group > each > radio\n\n```dil\n{@body const choices = [{id:"small",label:"Small"},{id:"large",label:"Large"}]}\n{@body const [size,setSize] = DIL.useState("small")}\n<radio-group aria-label="Size" value={size} onChange={setSize}>\n {#each choices as choice}<radio value={choice.id}>{choice.label}</radio>{/each}\n</radio-group>\n<caption>Selected: {size}</caption>\n```\n\n#### Component: segmented-control\n\n```dil\n{@body const [view,setView] = DIL.useState("summary")}\n<segmented-control aria-label="View" value={view} onChange={setView} options={[{value:"summary",label:"Summary"},{value:"details",label:"Details"}]}/>\n{#if view === "summary"}<text>Summary content.</text>{:else}<text>Detailed content.</text>{/if}\n```\n\n## 4. Specialized components\n\n### Data-linked components\n\n#### Task: external-data\n\nThese declarations represent records supplied in a prompt. The filter is local;\nno provider, fetch, subscription, or write-back channel is created.\n\n```dil\n{@body const records = [{id:"a",name:"Alpha",amount:12},{id:"b",name:"Beta",amount:18}]}\n{@body const [query,setQuery] = DIL.useState("")}\n{@body const visible = records.filter(item => item.name.toLowerCase().includes(query.toLowerCase()))}\n<input aria-label="Filter supplied records" value={query} onChange={setQuery}/>\n{#if visible.length > 0}\n <table>{#each visible as item}<table-row><table-cell>{item["name"]}</table-cell><table-cell>{item.amount}</table-cell></table-row>{/each}</table>\n{:else}\n <caption>No matching records.</caption>\n{/if}\n```\n\n### Links and citations\n\n#### Task: visible-source-url\n\nNo citation or navigable-link component exists. Display supplied references as\ntext; the explicit action below copies the address.\n\n```dil\n{@body const sourceUrl = "https://example.com/releases"}\n<title>Supplied release notes</title>\n<text>{sourceUrl}</text>\n<button onClick={() => GenUI.copy(sourceUrl)}>Copy URL</button>\n```\n\n### Embedded application blocks\n\n#### Task: local-application-panel\n\nThis is local UI composition. It does not embed or run another application.\n\n```dil\n{@body const [view,setView] = DIL.useState("overview")}\n<box border padding={4} gap={3}>\n <title>Review workspace</title>\n <segmented-control aria-label="Workspace view" value={view} onChange={setView} options={[{value:"overview",label:"Overview"},{value:"notes",label:"Notes"}]}/>\n {#if view === "overview"}<text>Two records prepared.</text>{:else}<caption>Notes remain in this local document.</caption>{/if}\n</box>\n```\n\n## 5. Visualizations\n\n### Images\n\n#### Component: svg\n\n#### Composition: svg > g > rect + circle + text\n\n```dil\n<caption>Static sample status drawing.</caption>\n<svg viewBox="0 0 240 100" width="100%" height={100}>\n <g>\n <rect x={5} y={5} width={230} height={90} rx={8} fill="#eeeeff"/>\n <circle cx={35} cy={50} r={12} fill="#16794b"/>\n <text x={60} y={56} fontSize={18} fill="#252838">Ready</text>\n </g>\n</svg>\n```\n\n#### SVG element: defs\n\n#### Composition: svg > defs > marker\n\n```dil\n<svg viewBox="0 0 200 50" width={200} height={50}>\n <defs><marker id="defs-arrow" markerWidth={10} markerHeight={10} refX={8} refY={3} orient="auto"><path d="M0 0 L8 3 L0 6 Z" fill="#5e4cff"/></marker></defs>\n <path d="M10 25 L180 25" stroke="#5e4cff" strokeWidth={2} markerEnd="url(#defs-arrow)"/>\n</svg>\n```\n\n#### SVG element: marker\n\n```dil\n<svg viewBox="0 0 200 50" width={200} height={50}>\n <defs><marker id="marker-arrow" markerWidth={10} markerHeight={10} refX={8} refY={3} orient="auto"><path d="M0 0 L8 3 L0 6 Z" fill="currentColor"/></marker></defs>\n <path d="M10 25 L180 25" stroke="currentColor" strokeWidth={2} markerEnd="url(#marker-arrow)"/>\n</svg>\n```\n\n#### SVG element: path\n\n```dil\n<svg viewBox="0 0 120 80" width={120} height={80}><path d="M10 65 L60 10 L110 65 Z" fill="#eeeeff" stroke="#5e4cff" strokeWidth={2}/></svg>\n```\n\n#### SVG element: rect\n\n```dil\n<svg viewBox="0 0 120 80" width={120} height={80}><rect x={10} y={10} width={100} height={60} rx={8} fill="#5e4cff"/></svg>\n```\n\n#### SVG element: circle\n\n```dil\n<svg viewBox="0 0 80 80" width={80} height={80}><circle cx={40} cy={40} r={25} fill="#16794b"/></svg>\n```\n\n#### SVG element: line\n\nThe element is recognized, but endpoint props x1/y1/x2/y2 are unavailable. Use\nthe path in this example for visible line geometry.\n\n```dil\n<svg viewBox="0 0 120 50" width={120} height={50}><line stroke="#5e4cff"/><path d="M10 25 L110 25" stroke="#5e4cff" strokeWidth={2}/></svg>\n```\n\n#### SVG element: polyline\n\nPoints is unavailable. The path shows the equivalent supported visible geometry.\n\n```dil\n<svg viewBox="0 0 120 80" width={120} height={80}><polyline fill="none" stroke="#5e4cff"/><path d="M10 60 L50 20 L100 60" fill="none" stroke="#5e4cff" strokeWidth={2}/></svg>\n```\n\n#### SVG element: polygon\n\nPoints is unavailable; use path for a visible closed polygon.\n\n```dil\n<svg viewBox="0 0 120 80" width={120} height={80}><polygon fill="#eeeeff"/><path d="M10 65 L60 10 L110 65 Z" fill="#eeeeff" stroke="#5e4cff"/></svg>\n```\n\n#### SVG element: g\n\n```dil\n<svg viewBox="0 0 140 80" width={140} height={80}><g fill="#5e4cff"><circle cx={35} cy={40} r={20}/><rect x={75} y={20} width={40} height={40}/></g></svg>\n```\n\n#### SVG element: ellipse\n\n```dil\n<svg viewBox="0 0 140 80" width={140} height={80}><ellipse cx={70} cy={40} rx={50} ry={25} fill="#eeeeff" stroke="#5e4cff"/></svg>\n```\n\n#### SVG element: text\n\nWithin SVG, text has SVG props and does not accept DIL color/size props.\n\n```dil\n<svg viewBox="0 0 160 60" width={160} height={60}><text x={10} y={35} fontSize={18} fontWeight={500} fill="currentColor">Alpha</text></svg>\n```\n\n#### SVG element: tspan\n\n#### Composition: svg > text > tspan\n\n```dil\n<svg viewBox="0 0 180 80" width={180} height={80}><text x={10} y={25} fontSize={16} fill="currentColor">Alpha<tspan x={10} y={55}>12 sample units</tspan></text></svg>\n```\n\n#### SVG element: linearGradient\n\n#### Composition: svg > defs > linearGradient > stop\n\nThe vocabulary recognizes gradient definitions, but offset/stopColor props are\nunavailable. This demonstrates accepted composition only; use solid fills for\nreliable authored color output.\n\n```dil\n<svg viewBox="0 0 120 60" width={120} height={60}>\n <defs><linearGradient id="limited-gradient"><stop/></linearGradient></defs>\n <rect x={10} y={10} width={100} height={40} fill="#5e4cff"/>\n</svg>\n```\n\n#### SVG element: stop\n\n```dil\n<svg viewBox="0 0 120 60" width={120} height={60}>\n <defs><linearGradient id="limited-stop"><stop opacity={1}/></linearGradient></defs>\n <rect x={10} y={10} width={100} height={40} fill="#5e4cff"/>\n</svg>\n```\n\n### Charts\n\n#### Component: Chart\n\n#### Chart type: line\n\n```dil\n<Chart content={{chartType:"line",data:[{month:"Jan",actual:10,plan:12},{month:"Feb",actual:15,plan:14}],xKey:"month",series:[{dataKey:"actual",label:"Actual"},{dataKey:"plan",label:"Plan"}]}}/>\n<caption>Synthetic units. Actual rises from 10 to 15.</caption>\n```\n\n#### Chart type: bar\n\n```dil\n<Chart content={{chartType:"bar",data:[{name:"Alpha",amount:12},{name:"Beta",amount:18}],xKey:"name",series:[{dataKey:"amount",label:"Units"}]}}/>\n<caption>Synthetic values: Alpha 12, Beta 18.</caption>\n```\n\n#### Chart type: scatter\n\n```dil\n<Chart content={{chartType:"scatter",data:[{hours:1,units:4},{hours:2,units:7},{hours:3,units:9}],xKey:"hours",series:[{dataKey:"units",label:"Units"}]}}/>\n<caption>Synthetic relationship between hours and units.</caption>\n```\n\n#### Chart type: pie\n\n```dil\n<Chart content={{chartType:"pie",data:[{name:"Alpha",amount:30},{name:"Beta",amount:70}],nameKey:"name",valueKey:"amount"}}/>\n<caption>Synthetic shares: Alpha 30%, Beta 70%.</caption>\n```\n\n#### Component: NodeGraph\n\n```dil\n{@body const [selectedId,setSelectedId] = DIL.useState("api")}\n{@body const graph = {nodes:[{id:"api",label:"API",sub:"Entry",x:0,y:0},{id:"db",label:"Database",sub:"Storage",x:250,y:0}],edges:[{id:"api-db",source:"api",target:"db",label:"reads"}]}}\n<NodeGraph content={graph} selectedId={selectedId} onSelect={setSelectedId}/>\n<text>Selected service: {selectedId}</text>\n```\n\n#### Component: Mermaid\n\n```dil\n<Mermaid source={"flowchart LR\\n Request --> Review\\n Review --> Ready"}/>\n```\n\n#### Syntax: mermaid-markdown-fence\n\nThis complete DIL example contains a Markdown Mermaid fence. The outer four-backtick\nfence belongs to this reference only; copy its inner source to the renderer.\n\n````dil\n```mermaid\nflowchart LR\n Alpha --> Beta\n```\n````\n\n### Maps\n\n#### Task: location-data-without-map\n\nNo map/geocoding adapter exists. Display coordinates as supplied.\n\n```dil\n{@body const places = [{id:"berlin",name:"Berlin",lat:52.52,lon:13.405}]}\n<table>{#each places as place}<table-row><table-cell>{place.name}</table-cell><table-cell>{place.lat}, {place.lon}</table-cell></table-row>{/each}</table>\n<caption>No map or geocoding service is connected.</caption>\n```\n\n## 6. Interactivity\n\n### State management\n\n#### Task: immutable-record-updates\n\n```dil\n{@body const [tasks,setTasks] = DIL.useState([{id:"a",name:"Review Alpha",done:false},{id:"b",name:"Review Beta",done:false}])}\n{@body const completeCount = tasks.filter(task => task.done).length}\n<text>{completeCount} of {tasks.length} complete</text>\n{#each tasks as task}\n <checkbox checked={task.done} onChange={checked => setTasks(previous => previous.map(entry => entry.id === task.id ? {...entry,done:checked} : entry))}>{task.name}</checkbox>\n{/each}\n```\n\n### Event callbacks\n\n#### Task: validation-form\n\nThe handler guards the action as well as disabling the control. No form or\nserver submission is implied.\n\n```dil\n{@body const [name,setName] = DIL.useState("")}\n{@body const valid = name.trim().length >= 2 && name.trim().length <= 80}\n<box gap={3} maxWidth={420}>\n <label>Name</label>\n <input aria-label="Name" value={name} onChange={setName} placeholder="At least two characters"/>\n {#if !valid}<caption color="danger">Enter a name between 2 and 80 characters.</caption>{/if}\n <button disabled={!valid} onClick={() => { if (valid) GenUI.copy(name.trim()); }}>Copy name</button>\n</box>\n```\n\n### Data bindings\n\n#### Task: computed-fields-and-derived-data\n\n```dil\n{@body const records = [{id:"a",name:"Alpha",amount:12},{id:"b",name:"Beta",amount:18}]}\n{@body const field = "name"}\n{@body const total = records.reduce((sum,item) => sum + item.amount,0)}\n<text>Total: {total}</text>\n{#each records as item}<text>{item[field]}: {item.amount}</text>{/each}\n```\n\n### Host actions\n\n#### Task: host-action\n\n```dil\n{@body const report = "Review complete: Alpha and Beta checked."}\n<button onClick={() => GenUI.copy(report)}><icon name="copy"/> Copy report</button>\n```\n\n#### Task: pressable-copy\n\n```dil\n<pressable border padding={4} radius="xl" gap={2} onClick={() => GenUI.copy("Alpha: 12 sample units")}>\n <title>Alpha</title><text>12 sample units</text><caption>Copy this summary</caption>\n</pressable>\n```\n\n## 7. Assets\n\n### Icons\n\n#### Component: icon\n\n#### Composition: button > icon + inline text\n\n```dil\n<button onClick={() => GenUI.copy("Review complete")}><icon name="copy" size="xs"/> Copy review</button>\n```\n\n#### Composition: button > icon with accessible action name\n\n```dil\n{@body const [count,setCount] = DIL.useState(1)}\n<button aria-label="Reset count" variant="ghost" onClick={() => setCount(0)}><icon name="rotate-ccw"/></button>\n<text>Count: {count}</text>\n```\n\n#### Assets: supported-icon-gallery\n\nAll supported names appear literally here for targeted searches. Icons are\ndecorative, so the gallery includes each name as visible text.\n\n```dil\n{@body const names = ["chart-no-axes-combined","circle-check","check-circle-2","circle","wallet","trending-up","users","rotate-ccw","copy","sliders-horizontal","ellipsis","sparkles","mouse-pointer-click","x","git-merge","package-check","shield-check","settings-2","info","code-2","alert-triangle"]}\n<grid columns={2} gap={3}>\n {#each names as name}<row gap={2} align="center"><icon name={name} size="lg"/><text>{name}</text></row>{/each}\n</grid>\n```\n';
5
+ export {
6
+ agentSpec,
7
+ agentSpecExamples,
8
+ agentSpecFull
9
+ };
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{createContext as R,useContext as k,useState as I,useMemo as E,useSyncExternalStore as M}from"react";import{clsx as _}from"clsx";import{twMerge as A}from"tailwind-merge";function a(...e){return A(_(e))}import{jsx as C,jsxs as D}from"react/jsx-runtime";var w=R({container:null});function s(){return k(w)}var O=R(null),y=()=>0,B=()=>()=>{};function m(e=0){let t=k(O),o=M(t?.subscribe??B,t?.below??y,y);if(!o)return e;let r=typeof e=="number"?{top:e,right:e,bottom:e,left:e}:e;return{...r,bottom:(r.bottom??0)-o}}function oe({children:e,className:t,style:o,appearance:r="light",tokens:n,boundary:i,...l}){let[v,b]=I(null),G=E(()=>({container:v,...i?{boundary:i}:{}}),[v,i]);return C("section",{...l,className:a("dil-scope",t),"data-theme":r,style:{...o,...n},children:D(w.Provider,{value:G,children:[e,C("div",{"data-dil-portals":!0,ref:b})]})})}import"react";import{Popover as c}from"radix-ui";import{jsx as d}from"react/jsx-runtime";function le({...e}){return d(c.Root,{"data-slot":"popover",...e})}function ce({...e}){return d(c.Trigger,{"data-slot":"popover-trigger",...e})}function pe(e){let{container:t}=s();return d(c.Portal,{container:t,children:d(H,{...e})})}function H({className:e,align:t="center",sideOffset:o=4,collisionPadding:r,...n}){let{boundary:i}=s();return d(c.Content,{"data-slot":"popover-content",align:t,sideOffset:o,collisionBoundary:i,collisionPadding:m(r),className:a("z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",e),...n})}function ue({...e}){return d(c.Anchor,{"data-slot":"popover-anchor",...e})}import"react";import{cva as U}from"class-variance-authority";import{Slot as L}from"radix-ui";import{jsx as q}from"react/jsx-runtime";var $=U("inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dil-dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/90",destructive:"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dil-dark:bg-destructive/60 dil-dark:focus-visible:ring-destructive/40",outline:"border bg-background text-foreground shadow-xs hover:bg-accent hover:text-accent-foreground dil-dark:border-input dil-dark:bg-input/30 dil-dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground dil-dark:hover:bg-accent/50",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2 has-[>svg]:px-3",xs:"h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",sm:"h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",lg:"h-10 rounded-md px-6 has-[>svg]:px-4",icon:"size-9","icon-xs":"size-6 rounded-md [&_svg:not([class*='size-'])]:size-3","icon-sm":"size-8","icon-lg":"size-10"}},defaultVariants:{variant:"default",size:"default"}});function he({className:e,variant:t="default",size:o="default",asChild:r=!1,...n}){let i=r?L.Root:"button";return q(i,{"data-slot":"button","data-variant":t,"data-size":o,className:a($({variant:t,size:o,className:e})),...n})}import{Tooltip as p}from"radix-ui";import{jsx as u,jsxs as J}from"react/jsx-runtime";function ke({label:e,children:t,open:o}){let{container:r}=s();return u(p.Provider,{delayDuration:250,children:J(p.Root,{...o===void 0?{}:{open:o},children:[u(p.Trigger,{asChild:!0,children:t}),u(p.Portal,{container:r,children:u(F,{label:e})})]})})}function F({label:e}){let{boundary:t}=s();return u(p.Content,{sideOffset:6,collisionPadding:m(8),collisionBoundary:t,className:"dil-tooltip",children:e})}import"react";import{CheckIcon as K}from"lucide-react";import{Checkbox as z}from"radix-ui";import{jsx as P}from"react/jsx-runtime";function Ge({className:e,...t}){return P(z.Root,{"data-slot":"checkbox",className:a("peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dil-dark:bg-input/30 dil-dark:aria-invalid:ring-destructive/40 dil-dark:data-[state=checked]:bg-primary",e),...t,children:P(z.Indicator,{"data-slot":"checkbox-indicator",className:"grid place-content-center text-current transition-none",children:P(K,{className:"size-3.5"})})})}import"react";import{jsx as Q}from"react/jsx-runtime";function Me({className:e,type:t,...o}){return Q("input",{type:t,"data-slot":"input",className:a("h-9 w-full min-w-0 rounded-md border border-input bg-transparent text-foreground px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dil-dark:bg-input/30","focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50","aria-invalid:border-destructive aria-invalid:ring-destructive/20 dil-dark:aria-invalid:ring-destructive/40",e),...o})}import*as T from"react";import{Slider as g}from"radix-ui";import{jsx as h,jsxs as W}from"react/jsx-runtime";function Ue({className:e,defaultValue:t,value:o,min:r=0,max:n=100,...i}){let l=T.useMemo(()=>Array.isArray(o)?o:Array.isArray(t)?t:[r,n],[o,t,r,n]);return W(g.Root,{"data-slot":"slider",defaultValue:t,value:o,min:r,max:n,className:a("relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",e),...i,children:[h(g.Track,{"data-slot":"slider-track",className:a("relative grow overflow-hidden rounded-full bg-muted data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"),children:h(g.Range,{"data-slot":"slider-range",className:a("absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full")})}),Array.from({length:l.length},(v,b)=>h(g.Thumb,{"aria-label":i["aria-label"],"aria-valuetext":i["aria-valuetext"],"data-slot":"slider-thumb",className:"block size-4 shrink-0 rounded-full border border-primary bg-white shadow-sm ring-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"},b))]})}import*as f from"react";import"class-variance-authority";import{ToggleGroup as S}from"radix-ui";import"react";import{cva as X}from"class-variance-authority";import{Toggle as Ke}from"radix-ui";import{jsx as We}from"react/jsx-runtime";var N=X("inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap text-foreground transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dil-dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",{variants:{variant:{default:"bg-transparent",outline:"border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"},size:{default:"h-9 min-w-9 px-2",sm:"h-8 min-w-8 px-1.5",lg:"h-10 min-w-10 px-2.5"}},defaultVariants:{variant:"default",size:"default"}});import{jsx as x}from"react/jsx-runtime";var V=f.createContext({size:"default",variant:"default",spacing:0});function tt({className:e,variant:t,size:o,spacing:r=0,segmented:n=!1,children:i,...l}){return x(S.Root,{"data-slot":"toggle-group","data-variant":t,"data-size":o,"data-spacing":r,style:{"--gap":r},className:a("group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs",n&&"max-w-full flex-wrap rounded-lg bg-secondary p-1",e),...l,children:x(V.Provider,{value:{variant:t,size:o,spacing:r},children:i})})}function ot({className:e,children:t,variant:o,size:r,...n}){let i=f.useContext(V);return x(S.Item,{"data-slot":"toggle-group-item","data-variant":i.variant||o,"data-size":i.size||r,"data-spacing":i.spacing,className:a(N({variant:i.variant||o,size:i.size||r}),"w-auto min-w-0 shrink-0 px-3 text-foreground data-[size=sm]:px-2 focus:z-10 focus-visible:z-10","rounded-md data-[state=on]:bg-background data-[state=on]:shadow-sm",e),...n,children:t})}export{a,s as b,oe as c,le as d,ce as e,pe as f,ue as g,$ as h,he as i,ke as j,Ge as k,Me as l,Ue as m,tt as n,ot as o};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{useCallback as C,useEffect as w,useRef as S,useMemo as j}from"react";function x(e){if(e===!1)return null;let t=e===!0?"instant":e.behavior??"instant",n=e===!0?0:e.padding??0;if(t!=="instant"&&t!=="smooth")throw new Error("Auto-scroll behavior must be instant or smooth.");if(!Number.isFinite(n)||n<0)throw new Error("Auto-scroll padding must be a finite nonnegative number.");return{behavior:t,padding:n}}function v(e){return typeof e=="object"&&e!==null&&"nodeType"in e&&e.nodeType===1}function T(e){if(e==null||e==="auto")return"auto";if(e==="window"||v(e)||typeof e=="object"&&"current"in e)return e;throw new Error('scrollContainer must be "auto", "window", an element, or a ref to an element.')}function L(e){return e==="window"||v(e)}function A(e){if(e==="window")return null;if(!(e==="auto"||e===null))return v(e)?e:v(e.current)?e.current:void 0}var f=class{constructor(t,n){this.view=t;this.element=n}view;element;get top(){return this.element?this.element.scrollTop:this.view.scrollY}get maximum(){let t=this.element??this.view.document.scrollingElement??this.view.document.documentElement,n=this.element?this.element.clientHeight:this.view.innerHeight;return Math.max(0,t.scrollHeight-n)}bounds(){let t=this.view.innerHeight;if(!this.element)return{top:0,bottom:t,width:this.view.document.documentElement.clientWidth};let r=this.element.getBoundingClientRect().top+this.element.clientTop,o=r+this.element.clientHeight,i=r<t&&o>0;return{top:i?Math.max(0,r):r,bottom:i?Math.min(t,o):o,width:this.element.clientWidth}}scrollTo(t){(this.element??this.view).scrollTo({top:t,behavior:"instant"})}get anchor(){return this.element??this.view.document.documentElement}contains(t){return!this.element||t.composedPath().includes(this.element)}scrollbar(t){if(!this.element)return t.clientX>=this.view.document.documentElement.clientWidth;if((t.composedPath()[0]??t.target)!==this.element)return!1;let n=this.element.getBoundingClientRect();return t.clientX>=n.left+this.element.clientLeft+this.element.clientWidth}};function g(e){if(e.assignedSlot)return e.assignedSlot;if(e.parentElement)return e.parentElement;let t=e.parentNode;return t&&"host"in t&&t.host instanceof Element?t.host:null}var W=8;function _(e){let{overflowY:t}=getComputedStyle(e);return(t==="auto"||t==="scroll"||t==="overlay")&&e.scrollHeight-e.clientHeight>W}function k(e){let t=e.ownerDocument,n=getComputedStyle(t.documentElement).overflowY==="visible"?t.body:null;for(let r=g(e);r&&r!==n&&r!==t.documentElement;r=g(r))if(r instanceof HTMLElement&&_(r))return r;return null}function H(e,t){let n=new Set([e.ownerDocument]);for(let o=g(e);o;o=g(o)){let i=o.getRootNode();i.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&n.add(i)}let r={capture:!0,passive:!0};return n.forEach(o=>o.addEventListener("scroll",t,r)),()=>n.forEach(o=>o.removeEventListener("scroll",t,r))}function D(e,t){for(let n=t;n;n=g(n))if(n===e)return!0;return!1}var y=new WeakMap;function O(e){let t=y.get(e);t||(t={owners:0,original:e.style.overflowAnchor},y.set(e,t),e.style.overflowAnchor="none"),t.owners++;let n=t;return()=>{--n.owners===0&&(e.style.overflowAnchor=n.original,y.delete(e))}}var E=class{constructor(t,n,r,o,i){this.element=t;this.settings=n;this.changed=r;this.roots=i;let l=t.ownerDocument.defaultView;if(!l)throw new Error("Following requires a browser document.");this.view=l,this.page=new f(l,null),this.reduced=l.matchMedia("(prefers-reduced-motion: reduce)"),this.reduced.addEventListener("change",this.refresh),this.observer=new ResizeObserver(this.refresh),this.observer.observe(t),this.unsubscribe=i?.subscribe(this.rebind)??(()=>{}),this.rebind(),this.unlisten=o(l,this.pause,()=>this.root)}element;settings;changed;roots;view;page;reduced;observer;unlisten;unsubscribe;releaseAnchor;observed=null;frame=0;previous=0;position;following=!1;notified=!1;ended=!1;gap=0;get root(){return this.roots?.current??this.page}rebind=()=>{let t=this.root.element;this.observed!==t&&(this.observed&&this.observer.unobserve(this.observed),t&&this.observer.observe(t),this.observed=t),this.releaseAnchor&&(this.releaseAnchor(),this.releaseAnchor=O(this.root.anchor),this.position=void 0),this.refresh()};report(t){this.following===t&&this.notified||(this.following=t,this.notified=!0,this.changed(t))}start(){this.ended=!1,this.resume()}end(){this.ended=!0,this.following?this.refresh():this.report(!1)}resume=()=>{this.element.isConnected&&(this.position=this.root.top,this.releaseAnchor??=O(this.root.anchor),this.report(!0),this.refresh())};pause=()=>{cancelAnimationFrame(this.frame),this.frame=0,this.position=void 0,this.releaseAnchor?.(),this.releaseAnchor=void 0,this.report(!1)};refresh=()=>{!this.following||this.frame||(this.previous=performance.now(),this.frame=requestAnimationFrame(this.tick))};tick=t=>{this.frame=0;let n=this.settings();if(!this.following||!n||!this.element.isConnected){this.pause();return}let r=this.root,o=r.top,i=Math.max(0,Math.min(r.maximum,o+this.element.getBoundingClientRect().bottom-r.bounds().bottom+n.padding)),l=this.position!==void 0&&Math.abs(o-this.position)>1.5;if(l&&this.ended&&Math.abs(i-o-this.gap)>1.5){this.pause();return}(this.position===void 0||l)&&(this.position=o);let h=n.behavior==="smooth"&&!this.reduced.matches,c=Math.min(64,Math.max(0,t-this.previous));this.previous=t,this.position=h?i+(this.position-i)*Math.exp(-c/80):i,Math.abs(i-this.position)<.5&&(this.position=i),r.scrollTo(this.position),this.gap=i-this.position,Math.abs(i-this.position)<.5&&Math.abs(i-r.top)<=1||(this.frame=requestAnimationFrame(this.tick))};dispose(){cancelAnimationFrame(this.frame),this.frame=0,this.releaseAnchor?.(),this.releaseAnchor=void 0,this.observer.disconnect(),this.unsubscribe(),this.unlisten(),this.reduced.removeEventListener("change",this.refresh)}};function I(e){return e instanceof Element&&!!e.closest('input, textarea, select, [contenteditable="true"], [role="slider"], [role="radio"]')}function X(e,t,n){let r=new f(e,null),o=n??(()=>r),i,l,h=!1,c=s=>{o().contains(s)&&t()},d=s=>{let u=s.composedPath()[0]??s.target,a=u===e.document.body||u===e.document.documentElement||u===e.document||u===e;!s.defaultPrevented&&(a||o().contains(s))&&!I(u)&&(["PageUp","PageDown","Home","End","ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].includes(s.key)||s.key===" "&&!(u instanceof Element&&u.closest("button, [role=button], [role=tab]")))&&t()},m=s=>{h=o().contains(s),i=s.touches[0]?.clientY,l=s.touches[0]?.clientX},p=s=>{if(!h)return;let u=s.touches[0]?.clientY,a=s.touches[0]?.clientX;a!==void 0&&l!==void 0&&a!==l&&t(),l=a,u!==void 0&&i!==void 0&&u!==i&&t(),i=u},b=s=>{let u=s.composedPath()[0]??s.target,a=o();(a.scrollbar(s)||a.contains(s)&&(s.button===1||u instanceof Element&&u.closest("a[href]")))&&t()};return e.addEventListener("wheel",c,{passive:!0}),e.addEventListener("keydown",d),e.addEventListener("touchstart",m,{passive:!0}),e.addEventListener("touchmove",p,{passive:!0}),e.addEventListener("pointerdown",b),()=>{e.removeEventListener("wheel",c),e.removeEventListener("keydown",d),e.removeEventListener("touchstart",m),e.removeEventListener("touchmove",p),e.removeEventListener("pointerdown",b)}}function ne(e,t,n,r,o){let i=x(t),l=i!==null,h=S(i),c=S(null),d=i?.behavior,m=i?.padding;w(()=>{h.current=d===void 0||m===void 0?null:{behavior:d,padding:m},c.current?.refresh()},[d,m]);let p=S(r);w(()=>{p.current=r},[r]);let b=C(()=>c.current?.pause(),[]),s=C(()=>c.current?.resume(),[]);return w(()=>{let u=e.current;if(!l||!u){p.current?.(!1);return}let a=new E(u,()=>h.current,U=>p.current?.(U),X,o);return c.current=a,()=>{a.dispose(),c.current=null}},[e,l,o]),w(()=>{n?c.current?.start():c.current?.end()},[n,l]),j(()=>({pause:b,resume:s}),[b,s])}import{useLayoutEffect as B,useState as q}from"react";var R=class{root=null;listeners=new Set;get current(){return this.root}rootFor(t){let n=t.ownerDocument.defaultView;return this.root||!n?this.root:new f(n,null)}subscribe(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}attach(t,n){let r=t.ownerDocument.defaultView;if(!r)return()=>{};let o=()=>{let c=A(n),d=c===void 0?k(t):c;this.root?.element!==d&&(this.root=new f(r,d),this.listeners.forEach(m=>m()))};if(o(),L(n))return()=>{this.root=null};let i=!0;queueMicrotask(()=>{i&&o()});let l=new ResizeObserver(o);l.observe(t);let h=H(t,c=>{let d=c.target;d instanceof r.Element&&d!==this.root?.element&&D(d,t)&&o()});return r.addEventListener("resize",o),()=>{i=!1,l.disconnect(),h(),r.removeEventListener("resize",o),this.root=null}}};function le(e,t,n=!0){let r=T(t),[o]=q(()=>new R);return B(()=>{let i=e.current;if(!(!n||!i))return o.attach(i,r)},[o,e,r,n]),o}function z(e){if(e===void 0||e==="instant")return"instant";if(typeof e=="number"&&Number.isFinite(e)&&e>=0)return e;throw new Error("Update interval must be instant or a finite nonnegative number of milliseconds.")}var N=class{pending=new Map;timer;last=-1/0;interval=0;disposed=!1;configure(t){let n=z(t);this.interval=n==="instant"?0:n,clearTimeout(this.timer),this.timer=void 0,this.pending.size&&(this.interval?this.schedule():this.flush())}enqueue(t,n,r=!1){if(!this.disposed){if(r||!this.interval){this.pending.delete(t),n();return}this.pending.set(t,n),this.schedule()}}cancel(t){this.pending.delete(t)}schedule(){this.timer===void 0&&(this.timer=setTimeout(()=>this.flush(),Math.max(0,this.last+this.interval-performance.now())))}flush(){this.timer=void 0;let t=[...this.pending.values()];if(this.pending.clear(),!(!t.length||this.disposed)){this.last=performance.now();for(let n of t)n()}}dispose(){this.disposed=!0,clearTimeout(this.timer),this.timer=void 0,this.pending.clear()}};var de="This part of the response couldn't be shown.",G=new Set(["incomplete","syntax","runtime","limit","source"]),P=2e3,M=20,K=`This message has more than ${M} problems; later ones are not reported.`,F=class{seen=new Set;count=0;ended=!1;take(t){let n={...t,message:t.message.slice(0,P)};if(n.kind==="incomplete")return this.ended?void 0:(this.ended=!0,n);let r=`${n.offset??""}:${n.message}`;if(!(this.count>M||this.seen.has(r)))return this.count++,this.count>M?{kind:"limit",message:K}:(this.seen.add(r),n)}};function ae(e,t){try{e?.(t)}catch(n){queueMicrotask(()=>{throw n})}}function he(e){if(!e||typeof e!="object")return;let{kind:t,message:n,offset:r}=e;if(typeof t!="string"||!G.has(t)||typeof n!="string")return;let o={kind:t,message:n.slice(0,P)};if(r===void 0)return o;if(!(typeof r!="number"||!Number.isSafeInteger(r)||r<0||r>5e6))return{...o,offset:r}}export{de as a,K as b,F as c,ae as d,he as e,H as f,D as g,ne as h,le as i,z as j,N as k};
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{c as oe,d as se,e as ie,f as ae,g as le,h as de,i as ce,j as pe}from"./chunk-ZSTXLIS6.js";import{Suspense as $e,use as je}from"react";import{useCallback as Oe,useEffect as u,useMemo as He,useRef as f,useState as T,useImperativeHandle as Ue}from"react";var I=class{constructor(t,n,s){this.frame=t;this.scroller=n;this.post=s;let o=t.ownerDocument.defaultView,a=new ResizeObserver(this.report);a.observe(t);let y=()=>{this.observed&&a.unobserve(this.observed),this.observed=n.current?.element??null,this.observed&&a.observe(this.observed),this.report()},v=n.subscribe(y);y();let A=ae(t,C=>{let b=C.target;(!o||!(b instanceof o.Element)||le(b,t))&&this.report()});o?.addEventListener("resize",this.report),this.stop=()=>{v(),a.disconnect(),A(),o?.removeEventListener("resize",this.report)}}frame;scroller;post;revision=0;lastOffset=0;observed=null;stop;visible(){let t=this.scroller.rootFor(this.frame),n=this.frame.getBoundingClientRect(),s=t?.bounds()??{top:0,bottom:innerHeight};return{root:t,box:n,bounds:s,offset:Math.max(0,s.top-n.top)}}report=()=>{let{box:t,bounds:n,offset:s}=this.visible();this.lastOffset=s;let o=t.bottom>n.top?n.bottom:t.bottom;this.post({type:"viewport",revision:++this.revision,offset:s,height:Math.max(0,Math.min(o,n.bottom)-Math.max(t.top,n.top)),width:t.width})};scroll(t,n){if(n!==this.revision)return;let{root:s,box:o,bounds:a,offset:y}=this.visible();s&&Math.abs(y-this.lastOffset)<2&&o.top<a.bottom&&o.bottom>a.top&&s.scrollTo(s.top+o.top-a.top+Math.max(0,Math.min(o.height,t)))}dispose(){this.stop()}};var Ae=/^--[A-Za-z0-9_-]{1,64}$/,Ce=/[;{}\\@<>!`\u0000-\u001f\u007f]|\/\*|\*\/|(?:url|image-set|image|cross-fade|element|src|expression)\s*\(/i;function Fe(e){return e.length<=256&&!Ce.test(e)&&e.split('"').length%2===1&&e.split("'").length%2===1}function ue(e){let t={},n=[];if(!e||typeof e!="object"||Array.isArray(e))return{tokens:t,rejected:n};for(let[s,[o,a]]of Object.entries(e).entries())s<256&&Ae.test(o)&&typeof a=="string"&&Fe(a)?t[o]=a:n.push(o.slice(0,80));return{tokens:t,rejected:n}}var me="0.2.0";var fe=new Set;function K(e,t){fe.has(e)||(fe.add(e),t())}function B(e){return`OpenDIL's runtime frame did not start from ${e}. Copy the runtime with "npx opendil copy-assets --out public/opendil" and set runtimeBaseUrl to the URL that serves it, including your app's base path.`}function he(e){K("start:"+e,()=>console.error("OpenDIL: "+B(e)+" The URL answered without the OpenDIL runtime; it may be missing or be your app's 404 or index page."))}function ge(e,t){if(t===me)return;let n=typeof t=="string"&&/^[\w.+-]{1,64}$/.test(t)?"version "+t:"an earlier version";K("version:"+e,()=>console.warn(`OpenDIL: the runtime frame at ${e} is ${n}, but the renderer is version ${me}. Run "npx opendil copy-assets --out <public directory>" again so the copied runtime matches the installed package.`))}function ye(e){for(let t of e)K("token:"+t,()=>console.warn(`OpenDIL: the iframe renderer ignores theme token ${JSON.stringify(t)}. Tokens must be CSS custom properties (--name) with values that cannot load resources or contain ; { } @ \\ ! < > or comments.`))}import{jsx as Re,jsxs as Ve}from"react/jsx-runtime";function be({ref:e,text:t,isStreaming:n=!1,showStatus:s=!0,progressiveReveal:o=!1,autoScroll:a=!1,scrollContainer:y="auto",updateInterval:v="instant",onFollowChange:A,runtimeBaseUrl:C="/opendil/",appearance:b="light",tokens:Se,onInput:F,onCommit:L,onError:N}){let w=C.replace(/\/$/,"")+"/frame.html",X=JSON.stringify(Se??{}),p=He(()=>{let{tokens:g,rejected:d}=ue(JSON.parse(X));return{appearance:b,tokens:g,rejected:d}},[b,X]);u(()=>ye(p.rejected),[p]);let[Me,ke]=T(!n),[xe,Te]=T(n);u(()=>{n&&Te(!0)},[n]);let D=f({onInput:F,onCommit:L,onError:N});u(()=>{D.current={onInput:F,onCommit:L,onError:N}},[F,L,N]);let J=f(null),m=Oe(g=>{J.current??=new oe;let d=J.current.take(g);d&&se(D.current.onError,d)},[]),S=f(null),O=ce(S,y),{pause:q,resume:G}=de(S,a,n||xe&&!Me,A,O);Ue(e,()=>({resumeAutoScroll:G}),[G]);let R=f(null),h=f({text:t,isStreaming:n,showStatus:s,progressiveReveal:o,updateInterval:v}),W=f(p),M=f(0),[De,Ee]=T(0),[E,Ie]=T(""),[k,Y]=T("");u(()=>{W.current=p,R.current?.postMessage(ve(p))},[p]),u(()=>{if(h.current={text:t,isStreaming:n,showStatus:s,progressiveReveal:o,updateInterval:v},!(t.length>5e6)){if(R.current&&t.length<M.current){queueMicrotask(()=>Ie("Start a new message instance before replacing its source."));return}R.current&&t.length>=M.current&&(R.current.postMessage({type:"source",suffix:t.slice(M.current),isStreaming:n,showStatus:s,progressiveReveal:o,updateInterval:v}),M.current=t.length)}},[t,n,s,o,v]);let Z=f("");u(()=>{let g=new URL(w,location.href).href,d,ee,U=()=>{d||(he(g),Y(B(g)))},V,te=Z.current===w?void 0:setTimeout(U,2e4),$=()=>{clearTimeout(te),clearTimeout(V)},re=()=>{clearTimeout(V),d||(V=setTimeout(U,3e3))},x=S.current;x?.addEventListener("load",re),x?.contentWindow?.postMessage({type:"dil-hello"},"*");let j=0,z=x?new I(x,O,c=>d?.port1.postMessage(c)):void 0,_e=(c,l)=>{d?.port1.close();let r=new MessageChannel;d=r,ee=l,Z.current=w,$(),Y(""),r.port1.onmessage=i=>Pe(r.port1,i),R.current=r.port1,c.postMessage({type:"dil-init"},{targetOrigin:"*",transfer:[r.port2]}),r.port1.postMessage(ve(W.current)),r.port1.postMessage({type:"source",suffix:h.current.text,isStreaming:h.current.isStreaming,showStatus:h.current.showStatus,progressiveReveal:h.current.progressiveReveal,updateInterval:h.current.updateInterval}),M.current=h.current.text.length,z?.report()},ne=c=>{if(!c.source||c.source!==S.current?.contentWindow||c.origin!=="null")return;let l=c.data;if(!l||typeof l!="object"||!("type"in l))return;l.type==="dil-loading"&&clearTimeout(te),l.type==="dil-failed"&&($(),U());let r="instance"in l?l.instance:void 0;l.type==="dil-ready"&&(!d||r!==ee)&&(ge(g,"version"in l?l.version:void 0),_e(c.source,r))},Pe=(c,l)=>{let r=l.data;if(!(!r||typeof r!="object"||!("type"in r))){if(r.type==="height"&&"height"in r&&typeof r.height=="number"&&Number.isFinite(r.height)&&Ee(Math.max(0,Math.min(4e6,Math.ceil(r.height)))),r.type==="scroll"&&"offset"in r&&typeof r.offset=="number"&&Number.isFinite(r.offset)&&"revision"in r&&typeof r.revision=="number"&&z?.scroll(r.offset,r.revision),r.type==="error"&&"error"in r){let i=ie(r.error);i&&m(i)}if(r.type==="gesture"&&(j=performance.now()+750),r.type==="reading"&&q(),r.type==="copy"&&"text"in r&&typeof r.text=="string"&&r.text.length<=65536&&navigator.userActivation.isActive&&performance.now()<j&&(j=0,navigator.clipboard.writeText(r.text).then(()=>c.postMessage({type:"copy-result",ok:!0})).catch(()=>c.postMessage({type:"copy-result",ok:!1}))),"detail"in r&&r.detail&&typeof r.detail=="object"){let i=r.detail;r.type==="commit"&&"scanned"in i&&typeof i.scanned=="number"&&Number.isFinite(i.scanned)&&"complete"in i&&typeof i.complete=="boolean"&&(ke(i.complete),D.current.onCommit?.({scanned:i.scanned,complete:i.complete,incomplete:"incomplete"in i&&i.incomplete===!0})),r.type==="input"&&"length"in i&&typeof i.length=="number"&&Number.isFinite(i.length)&&D.current.onInput?.({length:i.length})}}};return window.addEventListener("message",ne),()=>{$(),x?.removeEventListener("load",re),window.removeEventListener("message",ne),z?.dispose(),d?.port1.close(),R.current=null}},[q,m,w,O]);let H=t.length>5e6;u(()=>{E&&m({kind:"source",message:E})},[E,m]),u(()=>{H&&m({kind:"limit",message:"Message source limit exceeded"})},[H,m]),u(()=>{k&&m({kind:"runtime",message:k})},[k,m]);let Q=E||(H?"Message source limit exceeded":"")||k;return Ve("section",{"data-dil-message":!0,className:"dil-scope","data-theme":p.appearance,style:p.tokens,children:[Q&&Re("p",{role:"alert",children:Q}),Re("iframe",{ref:S,title:"DIL message",src:w,sandbox:"allow-scripts",referrerPolicy:"no-referrer",style:{width:"100%",height:De,border:0,colorScheme:p.appearance,display:k?"none":"block"}})]})}function ve(e){return{type:"theme",appearance:e.appearance,tokens:e.tokens}}import{jsx as P}from"react/jsx-runtime";var _;function we(){if(!_){let e=import("./styled-renderer-PHI4MNPF.js").then(t=>(Object.assign(e,{status:"fulfilled",value:t}),t),t=>{throw _=void 0,t});_=e}return _}async function ze(){await we()}function Ke(e){let t=je(we());return P(t.StyledRenderer,{...e})}var Be=["components","componentConfig","classNames","slots","className","shadowStyles"];function Xe(e){let t=pe(e.updateInterval);if(e.mode!=="host"&&e.mode!=="shadow"){let n=Be.filter(s=>e[s]!==void 0);if(n.length)throw new Error(`OpenDIL customization (${n.join(", ")}) requires mode="host" or mode="shadow".`);return P(be,{...e,updateInterval:t})}return P($e,{fallback:null,children:P(Ke,{mode:e.mode,rendererRef:e.ref,text:e.text,isStreaming:e.isStreaming??!1,showStatus:e.showStatus??!0,progressiveReveal:e.progressiveReveal??!1,autoScroll:e.autoScroll??!1,scrollContainer:e.scrollContainer,updateInterval:t,onFollowChange:e.onFollowChange,onInput:e.onInput,onCommit:e.onCommit,onError:e.onError,components:e.components,componentConfig:e.componentConfig,classNames:e.classNames,slots:e.slots,className:e.className,appearance:e.appearance??"light",tokens:e.tokens,shadowStyles:e.mode==="shadow"?e.shadowStyles:void 0})})}export{Xe as DilRenderer,ze as preloadHostRenderer};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ "use client";import{useEffect as c,useId as u,useState as l}from"react";import n from"mermaid";import p from"dompurify";import{jsx as o,jsxs as v}from"react/jsx-runtime";var g={startOnLoad:!1,securityLevel:"strict",maxTextSize:8192,maxEdges:100,htmlLabels:!1,flowchart:{htmlLabels:!1},theme:"neutral"};function y({source:e,presentationRef:m}){let r=u().replace(/[^a-zA-Z0-9]/g,""),[t,i]=l(""),[s,d]=l("");return c(()=>{let a=!0;if(i(""),e.length>8192||/%%\{|click\s|classDef\s|(?:^|\n)\s*(?:style|linkStyle)\s|<|^---/m.test(e)){queueMicrotask(()=>i("Unsupported or oversized Mermaid source"));return}return n.initialize(g),n.render("dil"+r,e).then(f=>{a&&d(p.sanitize(f.svg,{USE_PROFILES:{svg:!0,svgFilters:!1},FORBID_TAGS:["foreignObject","script","a"],FORBID_ATTR:["href","xlink:href"]}))}).catch(()=>{document.getElementById("ddil"+r)?.remove(),a&&i("Diagram is incomplete or invalid")}),()=>{a=!1}},[e,r]),!s&&!t?null:v("div",{ref:m,"aria-label":"Mermaid diagram",className:"overflow-hidden",children:[o("div",{dangerouslySetInnerHTML:{__html:s}}),t&&o("p",{role:"alert",children:t})]})}export{y as MermaidDiagram};