@snackbit/opendil 0.1.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.
- package/README.md +74 -137
- package/bin/opendil.mjs +66 -11
- package/bin/publish-directory.d.mts +18 -0
- package/bin/publish-directory.mjs +173 -17
- package/dist/agent-spec.js +9 -0
- package/dist/chunk-RPZW4WVX.js +2 -0
- package/dist/chunk-ZSTXLIS6.js +2 -0
- package/dist/index.js +1 -10
- package/dist/runtime/frame.html +117 -44
- package/dist/runtime/frame.js +501 -505
- package/dist/spec/genui.agent.full.md +1927 -0
- package/dist/spec/genui.agent.md +479 -0
- package/dist/spec/genui.examples.md +836 -0
- package/dist/styled-renderer-PHI4MNPF.js +2441 -0
- package/dist/styles.css +115 -42
- package/dist/types/agent-spec.d.ts +12 -0
- package/dist/types/components/ui/controls/select.d.ts +14 -0
- package/dist/types/components/ui/controls/tabs.d.ts +7 -0
- package/dist/types/components/ui/controls/toggle-group.d.ts +3 -2
- package/dist/types/components/ui/display/chart.d.ts +6 -12
- package/dist/types/components/ui/media/carousel.d.ts +1 -1
- package/dist/types/components/ui/overlays/collapsible.d.ts +6 -0
- package/dist/types/components/ui/overlays/popover.d.ts +2 -1
- package/dist/types/components/ui/overlays/ui-scope.d.ts +16 -0
- package/dist/types/dil/custom-component.d.ts +1 -1
- package/dist/types/dil/dil-renderer.d.ts +58 -23
- package/dist/types/dil/isolation/frame-startup.d.ts +18 -0
- package/dist/types/dil/isolation/frame-theme.d.ts +14 -0
- package/dist/types/dil/isolation/frame-viewport.d.ts +30 -0
- package/dist/types/dil/isolation/isolated-renderer.d.ts +13 -7
- package/dist/types/dil/isolation/overlay-room.d.ts +29 -0
- package/dist/types/dil/isolation/viewport-scroll.d.ts +3 -2
- package/dist/types/dil/message-renderer.d.ts +6 -5
- package/dist/types/dil/parser/dil-parser.d.ts +44 -3
- package/dist/types/dil/parser/lexical.d.ts +13 -2
- package/dist/types/dil/parser/literal-tag.d.ts +16 -0
- package/dist/types/dil/parser/markdown-lexing.d.ts +41 -0
- package/dist/types/dil/parser/types.d.ts +22 -1
- package/dist/types/dil/parser/unfinished.d.ts +22 -0
- package/dist/types/dil/parser/vocabulary.d.ts +12 -0
- package/dist/types/dil/render-error.d.ts +47 -0
- package/dist/types/dil/renderer-environment.d.ts +19 -8
- package/dist/types/dil/runtime/document.d.ts +18 -6
- package/dist/types/dil/runtime/execution-queue.d.ts +2 -1
- package/dist/types/dil/runtime/expressions.d.ts +8 -5
- package/dist/types/dil/runtime/inline-worker.d.ts +33 -0
- package/dist/types/dil/runtime/view-cost.d.ts +2 -2
- package/dist/types/dil/styled-renderer.d.ts +39 -0
- package/dist/types/dil/view/conditional-view.d.ts +3 -3
- package/dist/types/dil/view/markdown-node.d.ts +3 -3
- package/dist/types/dil/view/node-children.d.ts +3 -3
- package/dist/types/dil/view/node-view.d.ts +2 -2
- package/dist/types/dil/view/progressive-reveal.d.ts +5 -4
- package/dist/types/dil/view/render-boundary.d.ts +13 -0
- package/dist/types/dil/view/render-limit.d.ts +1 -1
- package/dist/types/dil/view/repeated-nodes.d.ts +4 -4
- package/dist/types/dil/view/reveal/controller.d.ts +9 -2
- package/dist/types/dil/view/reveal/presentation.d.ts +1 -1
- package/dist/types/dil/view/scroll/controller.d.ts +16 -2
- package/dist/types/dil/view/scroll/host-viewport.d.ts +24 -0
- package/dist/types/dil/view/scroll/root-tracker.d.ts +17 -0
- package/dist/types/dil/view/scroll/scroll-root.d.ts +36 -0
- package/dist/types/dil/view/scroll-options.d.ts +15 -0
- package/dist/types/dil/view/stream-follow.d.ts +10 -3
- package/dist/types/dil/view/table-context.d.ts +1 -1
- package/dist/types/dil/view/virtual-flow.d.ts +3 -3
- package/dist/types/dil/widgets/action-feedback.d.ts +1 -1
- package/dist/types/dil/widgets/charts/chart-hover.d.ts +17 -0
- package/dist/types/dil/widgets/charts/chart-legend.d.ts +1 -1
- package/dist/types/dil/widgets/charts/chart-pie.d.ts +16 -0
- package/dist/types/dil/widgets/charts/chart-series.d.ts +10 -2
- package/dist/types/dil/widgets/charts/chart-snapping.d.ts +3 -5
- package/dist/types/dil/widgets/charts/snap-cursor.d.ts +3 -7
- package/dist/types/dil/widgets/charts/snap-tooltip.d.ts +6 -4
- package/dist/types/dil/widgets/code-block.d.ts +1 -1
- package/dist/types/dil/widgets/controls.d.ts +2 -2
- package/dist/types/dil/widgets/graphs/node-graph.d.ts +1 -1
- package/dist/types/dil/widgets/graphs/service-node.d.ts +1 -1
- package/dist/types/dil/widgets/primitives/primitive.d.ts +4 -4
- package/dist/types/index.d.ts +9 -8
- package/dist/types/ui.d.ts +11 -8
- package/dist/ui.js +1 -1
- package/package.json +13 -2
- package/styles/tailwind.css +53 -1
- package/styles/tokens.css +3 -0
- package/dist/chunk-ZWAN2JCV.js +0 -2
- package/dist/runtime/vm.js +0 -6
- package/dist/shadow-renderer-F25KL3C4.js +0 -2363
|
@@ -0,0 +1,1927 @@
|
|
|
1
|
+
# GenUI Agent Specification: Full Reference
|
|
2
|
+
|
|
3
|
+
Use this reference for targeted lookups. Inject [the primary specification](genui.agent.md)
|
|
4
|
+
when the smaller instruction set is sufficient. Search `Component: NAME`,
|
|
5
|
+
`Composition: NAME`, `Callback: NAME`, or `Task: NAME`. Find complete runnable
|
|
6
|
+
recipes in [the example catalog](genui.examples.md). All names are case-sensitive.
|
|
7
|
+
The numbered sections and component groups match the primary specification.
|
|
8
|
+
|
|
9
|
+
## 1. Output format and safety
|
|
10
|
+
|
|
11
|
+
Generate declarative OpenDIL source. Combine ordinary Markdown with supported
|
|
12
|
+
components and directives. Return the source directly when asked to generate UI.
|
|
13
|
+
Use a code fence only when the user asks to inspect or copy source rather than
|
|
14
|
+
render it. Do not include an explanation of how to install React, a component
|
|
15
|
+
module, a package manifest, or a web page around a generated interface.
|
|
16
|
+
|
|
17
|
+
Treat the supported vocabulary as closed unless the host explicitly supplies a
|
|
18
|
+
custom component contract. A familiar HTML, React, Recharts, or SVG API is not
|
|
19
|
+
automatically an OpenDIL API. Match every tag, prop, callback name, and data shape
|
|
20
|
+
in this reference. A tag being accepted by the parser does not establish that a
|
|
21
|
+
renderer exists for it. An unknown prop may be ignored rather than reported.
|
|
22
|
+
Generate valid output deliberately instead of depending on fallback behavior.
|
|
23
|
+
|
|
24
|
+
Use Markdown for prose, real components for controls, and directives for UI
|
|
25
|
+
structure. Do not encode an entire interface as a string expression. Strings
|
|
26
|
+
returned by expressions are displayed as text, not parsed as nested DIL. Do not
|
|
27
|
+
construct HTML strings, use `dangerouslySetInnerHTML`, or request arbitrary CSS.
|
|
28
|
+
There is no authorable HTML document, React component function, import statement,
|
|
29
|
+
stylesheet, or JavaScript module boundary.
|
|
30
|
+
|
|
31
|
+
Close elements and control directives in the reverse order in which they open.
|
|
32
|
+
Write leaves as self-closing tags. Finish incomplete tokens before ending the
|
|
33
|
+
response. Keep the source readable enough that a later agent can locate a binding
|
|
34
|
+
or handler. Prefer one declaration per line and modest component trees. Avoid
|
|
35
|
+
deep wrappers that add no layout, semantics, or interaction value.
|
|
36
|
+
|
|
37
|
+
Use only facts supplied by the user or the enclosing application. Label synthetic
|
|
38
|
+
examples, estimated totals, and placeholder illustrations appropriately. Do not
|
|
39
|
+
present a disconnected chart as live telemetry or a local form as a completed
|
|
40
|
+
server submission. Render supplied source titles and URLs accurately. Do not
|
|
41
|
+
invent citation IDs, external services, host actions, or automatic data refresh.
|
|
42
|
+
|
|
43
|
+
Give controls meaningful names. Use visible labels where possible and explicit
|
|
44
|
+
`aria-label` on controls that expose it. Keep status text next to status colors.
|
|
45
|
+
Provide textual summaries for charts, SVG drawings, and node graphs. An icon is
|
|
46
|
+
decorative; it cannot replace the name of an action. Avoid interactive descendants
|
|
47
|
+
inside an interactive ancestor, including buttons inside pressable cards.
|
|
48
|
+
|
|
49
|
+
Keep data transformations bounded. Prefer a short filter, map, or reduce over
|
|
50
|
+
recursive traversal or large generated allocations. Do not run arbitrary code
|
|
51
|
+
received in a data record. Never use an expression to discover undocumented host
|
|
52
|
+
globals or alter the execution environment. Do not use `eval`, `Function`, dynamic
|
|
53
|
+
imports, or VM implementation globals in authored output.
|
|
54
|
+
|
|
55
|
+
Execution boundaries:
|
|
56
|
+
|
|
57
|
+
| Surface | Supported author behavior |
|
|
58
|
+
| --------------------------- | ------------------------------------------------------------ |
|
|
59
|
+
| Markdown and component tree | Declare content and supported props |
|
|
60
|
+
| QuickJS worker | Evaluate expressions, declarations, and supported callbacks |
|
|
61
|
+
| Renderer | Present approved widgets and dispatch their supported events |
|
|
62
|
+
| Host boundary | Receive explicitly authorized clipboard requests |
|
|
63
|
+
| Server | No generated server code or server action API |
|
|
64
|
+
|
|
65
|
+
The document expression environment does not expose browser `window`, `document`,
|
|
66
|
+
DOM nodes/events, `fetch`, XMLHttpRequest, WebSocket, localStorage, IndexedDB,
|
|
67
|
+
browser timers, or Node facilities. Do not assume that because the renderer uses
|
|
68
|
+
these internally, document expressions can call them. Native JavaScript features
|
|
69
|
+
such as arrays, objects, functions, and arithmetic remain available inside QuickJS.
|
|
70
|
+
The prohibition on `eval` and `Function` is an authoring rule; do not describe it
|
|
71
|
+
as a proven removal of those primitives from the VM.
|
|
72
|
+
|
|
73
|
+
The default renderer uses an opaque-origin frame. Host DOM and Shadow DOM modes
|
|
74
|
+
are explicit consumer choices with different containment properties. Shadow DOM
|
|
75
|
+
provides styling separation, not iframe containment. Generated source cannot
|
|
76
|
+
select a rendering mode or authorize new APIs. Do not tell a user to weaken
|
|
77
|
+
containment to make an unsupported feature work.
|
|
78
|
+
|
|
79
|
+
Resource constraints are bounds, not generation targets. Current VM limits are
|
|
80
|
+
64 MiB heap, 64 KiB stack, and an interpreter interrupt after more than 256 polls.
|
|
81
|
+
The worker transport also has a 1-second timeout. There is no promised 50 ms
|
|
82
|
+
evaluation budget. Execution speed depends on the device and work performed.
|
|
83
|
+
Encoded results and dependency metadata are limited to 524,288 characters each;
|
|
84
|
+
encoding rejects excessive structural depth. Keep data and calculations small.
|
|
85
|
+
Display limits can stop a document even when its JavaScript evaluation succeeds.
|
|
86
|
+
|
|
87
|
+
#### Task: output-review
|
|
88
|
+
|
|
89
|
+
Before finishing, check that every used tag and prop appears in this reference,
|
|
90
|
+
every named binding is declared before its consumer, each callback accepts the
|
|
91
|
+
documented value type, all control branches close, and every displayed claim is
|
|
92
|
+
supported by supplied data. Remove inert action buttons unless they intentionally
|
|
93
|
+
demonstrate appearance. Do not add an implementation checklist to the generated UI.
|
|
94
|
+
|
|
95
|
+
## 2. Syntax and parsing
|
|
96
|
+
|
|
97
|
+
### Markdown
|
|
98
|
+
|
|
99
|
+
Write paragraphs, headings, ordered/unordered lists, emphasis, blockquotes, code
|
|
100
|
+
fences, and GitHub-flavored tables, task lists, and strikethrough. Use Markdown
|
|
101
|
+
headings for the overall document outline. A DIL title is a styled h3 and does
|
|
102
|
+
not choose an arbitrary heading level. Use ordinary prose when no special layout
|
|
103
|
+
or control is needed.
|
|
104
|
+
|
|
105
|
+
Separate paragraphs and major blocks with blank lines. Keep indentation consistent
|
|
106
|
+
within component children; the renderer normalizes Markdown indentation but is
|
|
107
|
+
not an MDX compiler. Avoid relying on a large indentation offset to create code
|
|
108
|
+
blocks inside a layout. Use explicit fences or CodeBlock for source displays.
|
|
109
|
+
|
|
110
|
+
Markdown links are deliberately displayed as inert text spans containing their
|
|
111
|
+
labels. They do not open their href. Markdown images are suppressed. Use a visible
|
|
112
|
+
plain-text URL if the reader needs the destination, and do not promise that
|
|
113
|
+
clicking it navigates. There is no DIL anchor or image tag to restore browser
|
|
114
|
+
behavior. Bare URLs can be recognized by GFM but still render without navigation.
|
|
115
|
+
|
|
116
|
+
Task-list checkboxes are Markdown presentation. They do not provide onChange,
|
|
117
|
+
state binding, or an action target. Use the checkbox component for user-editable
|
|
118
|
+
choices. A Markdown table is useful for ordinary tabular prose; use the DIL table
|
|
119
|
+
composition when cells contain components or reactive controls.
|
|
120
|
+
|
|
121
|
+
Fenced code protects its contents from DIL parsing. Put triple backticks or triple
|
|
122
|
+
tildes at the beginning of a line, with no more than three preceding spaces.
|
|
123
|
+
Close the fence with the same marker on a line of its own. A longer fence, such as
|
|
124
|
+
four backticks, can enclose lines that start with three.
|
|
125
|
+
A `mermaid` language fence renders a Mermaid diagram rather than ordinary code.
|
|
126
|
+
Other language labels request display syntax, not code execution.
|
|
127
|
+
|
|
128
|
+
Inline code spans follow Markdown: a run of one or more backticks opens a span
|
|
129
|
+
that the next run of the same length closes. Braces, tags, and directives inside
|
|
130
|
+
a span display literally and never evaluate, so `{ leading: false }` or `<div>`
|
|
131
|
+
in backticks is safe in prose. A span cannot cross a blank line or continue into
|
|
132
|
+
a line that starts another block: a list item, heading, blockquote, fence,
|
|
133
|
+
component tag, or block directive such as `{:else}`. A component tag later on
|
|
134
|
+
the same line stays inside the span. An unmatched backtick protects nothing, and
|
|
135
|
+
a backslash before a backtick makes it literal. A closing fence may be followed
|
|
136
|
+
on its line by a component closing tag or block directive.
|
|
137
|
+
|
|
138
|
+
Lowercase HTML-like tags that are not DIL tags, such as `<div>`, `</span>`, or
|
|
139
|
+
`<br/>`, display as plain text up to their closing `>`, and so do autolinks such
|
|
140
|
+
as `<https://example.com>`. Their quoted or braced attribute values stay text,
|
|
141
|
+
but any other brace is an expression again, so `a<b then {total}` shows the
|
|
142
|
+
value. Do not rely on this to format output; use Markdown or DIL components. A
|
|
143
|
+
capitalized tag that is not a supported component renders an
|
|
144
|
+
unsupported-component error in its place. To insert a brace in prose, interpolate
|
|
145
|
+
a string containing it. Entity spellings can have Markdown-dependent display
|
|
146
|
+
behavior; use a string expression when exact text matters.
|
|
147
|
+
|
|
148
|
+
```dil
|
|
149
|
+
# Review summary
|
|
150
|
+
|
|
151
|
+
**Ready** for review. The sample contains synthetic values.
|
|
152
|
+
|
|
153
|
+
- Static prose uses Markdown.
|
|
154
|
+
- Interactive choices use supported components.
|
|
155
|
+
|
|
156
|
+
| Item | Value |
|
|
157
|
+
| --- | --- |
|
|
158
|
+
| Example records | 2 |
|
|
159
|
+
|
|
160
|
+
<text>A literal brace: {"{"}</text>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Markdown expressions are inserted as text after Markdown parsing. Do not expect a
|
|
164
|
+
string containing `**bold**` to become emphasis, a string containing a tag to
|
|
165
|
+
become a component, or an interpolated URL to become a live link. Put the needed
|
|
166
|
+
formatting around the expression in authored source instead.
|
|
167
|
+
|
|
168
|
+
### JavaScript expressions
|
|
169
|
+
|
|
170
|
+
Use `{expression}` in text or `property={expression}` in attributes. The outer
|
|
171
|
+
braces delimit JavaScript; an object value therefore needs its own object braces,
|
|
172
|
+
as in `content={{chartType:"bar",data:[]}}`. Numbers written in quoted attributes
|
|
173
|
+
remain strings. Supply numeric props with braces, including slider min/max/step,
|
|
174
|
+
layout spacing, dimensions, and SVG numeric coordinates.
|
|
175
|
+
|
|
176
|
+
Attribute forms:
|
|
177
|
+
|
|
178
|
+
| Form | Meaning |
|
|
179
|
+
| -------------------------------------- | ------------------- |
|
|
180
|
+
| `color="secondary"` | String literal |
|
|
181
|
+
| `color='secondary'` | String literal |
|
|
182
|
+
| `border` | Boolean true |
|
|
183
|
+
| `border={false}` | Boolean false |
|
|
184
|
+
| `padding={4}` | Number |
|
|
185
|
+
| `value={name}` | Evaluated binding |
|
|
186
|
+
| `onChange={setName}` | Callback reference |
|
|
187
|
+
| `onClick={() => setCount(n => n + 1)}` | Function expression |
|
|
188
|
+
|
|
189
|
+
Quoted attributes use a simple delimiter scan. Do not rely on JavaScript-style
|
|
190
|
+
backslash escaping inside a quoted attribute. For text containing its surrounding
|
|
191
|
+
quote, use a JavaScript string expression. Do not repeat an attribute; the parser
|
|
192
|
+
can overwrite earlier entries, which is not a useful generation contract.
|
|
193
|
+
Unquoted scalar values, JSX spread syntax, shorthand object props, and arbitrary
|
|
194
|
+
attribute fragments are unsupported.
|
|
195
|
+
|
|
196
|
+
Expressions use ordinary JavaScript arithmetic, comparisons, logical operators,
|
|
197
|
+
ternaries, optional chaining, nullish coalescing, property access, computed property
|
|
198
|
+
names, string/array/object literals, template strings, and functions. Array
|
|
199
|
+
filter/map/reduce/find/some/every and string transformations work as JavaScript
|
|
200
|
+
operations. Keep transformations pure and their output JSON-compatible.
|
|
201
|
+
|
|
202
|
+
```dil
|
|
203
|
+
{@body const item = {name:"Ada",hours:3,rate:20}}
|
|
204
|
+
{@body const field = "name"}
|
|
205
|
+
<text>{item[field]}: {item.hours * item.rate}</text>
|
|
206
|
+
<caption>{`Hours: ${item.hours}`}</caption>
|
|
207
|
+
<input aria-label="Quoted example" value={'Say "hello"'} disabled/>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Interpolation display:
|
|
211
|
+
|
|
212
|
+
| Evaluated value | Text output |
|
|
213
|
+
| ----------------------- | ------------------- |
|
|
214
|
+
| String or finite number | Its displayed value |
|
|
215
|
+
| true / false | `true` / `false` |
|
|
216
|
+
| null / undefined | Empty text |
|
|
217
|
+
| Object or array | `[object Object]` |
|
|
218
|
+
|
|
219
|
+
Use `items.join(", ")` for a text list, `JSON.stringify(record)` for intentionally
|
|
220
|
+
displayed JSON, or an each directive for repeated UI. Arrays returned by map do
|
|
221
|
+
not become React children. JavaScript cannot contain authored JSX elements.
|
|
222
|
+
Do not create UI using string concatenation and expect interpolation to parse it.
|
|
223
|
+
|
|
224
|
+
The bridge serializes data using JSON and represents callback functions with
|
|
225
|
+
internal handles. Do not author or inspect those handles. Avoid circular records,
|
|
226
|
+
BigInt, sparse data that relies on undefined, Map/Set instances, prototype-based
|
|
227
|
+
objects, or objects with behavior in serialization. Non-finite numbers do not
|
|
228
|
+
retain useful numeric meaning across JSON serialization. Use plain records,
|
|
229
|
+
arrays, strings, booleans, null, and finite numbers.
|
|
230
|
+
|
|
231
|
+
Keep statements out of expression positions. Assignments and updates may be valid
|
|
232
|
+
JavaScript expressions but are forbidden generation patterns during rendering.
|
|
233
|
+
Use callback bodies for state changes. A handler may use local const declarations,
|
|
234
|
+
an if guard, and a bounded loop, but simpler immutable transformations are preferred.
|
|
235
|
+
Do not use top-level await, imports, exports, or async resource work.
|
|
236
|
+
|
|
237
|
+
`Intl.NumberFormat` is a limited host bridge. Its format operation uses en-US
|
|
238
|
+
formatting with maximumFractionDigits=0; supplied locale and options do not
|
|
239
|
+
configure the formatter. It is not a full Intl implementation. For fixed decimal
|
|
240
|
+
precision, use a bounded numeric expression and `.toFixed(n)`. Do not promise
|
|
241
|
+
currency/locale behavior from the bridge that the implementation does not provide.
|
|
242
|
+
|
|
243
|
+
#### Task: format-values
|
|
244
|
+
|
|
245
|
+
```dil
|
|
246
|
+
{@body const amount = 1234.5}
|
|
247
|
+
<text>{new Intl.NumberFormat().format(amount)}</text>
|
|
248
|
+
<caption>{amount.toFixed(2)} units</caption>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### State declarations
|
|
252
|
+
|
|
253
|
+
Use one `{@body ...}` directive for each declaration. Place declarations before
|
|
254
|
+
the interface. The supported forms are deliberately narrower than a JavaScript
|
|
255
|
+
program body:
|
|
256
|
+
|
|
257
|
+
```text
|
|
258
|
+
{@body const [name,setName] = DIL.useState(initialValue)}
|
|
259
|
+
{@body const name = expression}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
An optional final semicolon is accepted. Use names beginning with a letter or
|
|
263
|
+
underscore and containing only letters, digits, and underscores. Avoid keywords,
|
|
264
|
+
duplicate names, builtin names, DIL, GenUI, and implementation-like double-underscore
|
|
265
|
+
names. Though some JavaScript identifiers allow `$` or Unicode, declaration
|
|
266
|
+
recognition is narrower; use the stated subset for reliable generation.
|
|
267
|
+
|
|
268
|
+
Only the exact state-pair destructuring shape is supported. Do not omit the setter,
|
|
269
|
+
add a third item, destructure objects, use nested patterns, or declare several
|
|
270
|
+
bindings in one directive. Ordinary const declarations create derived expression
|
|
271
|
+
bindings. There is no let/var declaration mode, function statement declaration,
|
|
272
|
+
class statement, or arbitrary script block. A function can be a const expression.
|
|
273
|
+
|
|
274
|
+
State initialization is once per state name in the mounted document. An initializer
|
|
275
|
+
may be a value or a function returning the initial value. Keep it side-effect-free.
|
|
276
|
+
Do not put a clipboard operation or setter call in initialization. State setters
|
|
277
|
+
accept either a replacement value or an updater function receiving the previous
|
|
278
|
+
value. A function passed to the setter is treated as an updater; do not use state
|
|
279
|
+
as a general function store.
|
|
280
|
+
|
|
281
|
+
Ordinary const bindings are getters. Their expression is recomputed when read;
|
|
282
|
+
they are not once-only snapshots and do not memoize expensive work. A getter can
|
|
283
|
+
read state and other bindings. Keep dependency order straightforward and avoid
|
|
284
|
+
cycles. A derived callback can be declared as a const function expression and
|
|
285
|
+
passed to a supported event prop.
|
|
286
|
+
|
|
287
|
+
```dil
|
|
288
|
+
{@body const [quantity,setQuantity] = DIL.useState(() => 2)}
|
|
289
|
+
{@body const unitPrice = 15}
|
|
290
|
+
{@body const total = quantity * unitPrice}
|
|
291
|
+
{@body const addOne = () => setQuantity(previous => previous + 1)}
|
|
292
|
+
<button onClick={addOne}>Add one</button>
|
|
293
|
+
<text>{quantity} items: {total} units</text>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
All body declarations belong to the document, even when their source is written
|
|
297
|
+
inside a conditional or each block. Parsing collects declarations independently
|
|
298
|
+
of which visual branch later renders. A declaration inside a loop does not run
|
|
299
|
+
once per item and does not inherit item/index bindings. Generate unconditional
|
|
300
|
+
top-level declarations and keep per-item state in a top-level keyed object/array.
|
|
301
|
+
|
|
302
|
+
Do not rely on duplicate state declarations to reset a value. A matching existing
|
|
303
|
+
state name retains state; collisions between state, setter, and derived names can
|
|
304
|
+
fail or redefine bindings. Give each state pair and derived binding a unique name.
|
|
305
|
+
Use a reset button calling the setter when a reset is required.
|
|
306
|
+
|
|
307
|
+
No useEffect, useMemo, useCallback, useRef, or useId hook is exposed to DIL source.
|
|
308
|
+
The renderer may use React hooks internally; they are not document hooks. Do not
|
|
309
|
+
translate a React example into DIL by retaining arbitrary hook calls. Replace
|
|
310
|
+
computed values with const getters and user effects with supported event handlers.
|
|
311
|
+
|
|
312
|
+
### Conditional rendering
|
|
313
|
+
|
|
314
|
+
Use `{#if condition}`, optional `{:else if condition}` branches, optional
|
|
315
|
+
`{:else}`, and `{/if}`. Conditions use JavaScript truthiness. The first matching
|
|
316
|
+
branch is selected. With no match and no else, nothing renders. Keep else-if and
|
|
317
|
+
else within their enclosing if and close nested branches before outer branches.
|
|
318
|
+
|
|
319
|
+
```dil
|
|
320
|
+
{@body const [level,setLevel] = DIL.useState(0)}
|
|
321
|
+
<slider aria-label="Level" min={0} max={10} step={1} value={level} onChange={setLevel}/>
|
|
322
|
+
{#if level >= 8}
|
|
323
|
+
<badge color="warning">High</badge>
|
|
324
|
+
{:else if level > 0}
|
|
325
|
+
<badge color="success">Active</badge>
|
|
326
|
+
{:else}
|
|
327
|
+
<caption>Not started</caption>
|
|
328
|
+
{/if}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
A conditional changes visibility, not declaration scope or document state lifetime.
|
|
332
|
+
Hiding an input does not erase its top-level state. If the next interaction needs
|
|
333
|
+
a reset, perform that reset explicitly in a callback. Keep data guards before
|
|
334
|
+
unsafe property reads inside rendered expressions; the renderer can evaluate
|
|
335
|
+
branch conditions while resolving which branch to present.
|
|
336
|
+
|
|
337
|
+
Repeat with `{#each expression as item}` or
|
|
338
|
+
`{#each expression as item,index}` and close with `{/each}`. The expression should
|
|
339
|
+
evaluate to an array. Non-arrays currently produce no items rather than a typed
|
|
340
|
+
error. Do not depend on that fallback to represent loading or a failed request.
|
|
341
|
+
Use an explicit empty-array branch and truthful status text.
|
|
342
|
+
|
|
343
|
+
Within repeated rendered content, item is the current value and index is its
|
|
344
|
+
zero-based position. Nested repeats can read outer scope bindings. Choose
|
|
345
|
+
different variable names for outer and inner items to avoid accidental shadowing.
|
|
346
|
+
Declare shared transformations outside the repeat only when they do not need an
|
|
347
|
+
item binding. Otherwise compute the small expression inline.
|
|
348
|
+
|
|
349
|
+
Use stable unique string or numeric `id` properties on repeated objects. Without
|
|
350
|
+
such an ID, identity falls back to index. Reordering a positional list can attach
|
|
351
|
+
local widget state to a different record. The language has no key prop, keyed-each
|
|
352
|
+
suffix, or custom key callback. Do not invent one. Allocate IDs when creating new
|
|
353
|
+
records, not from the current array position after filtering.
|
|
354
|
+
|
|
355
|
+
```dil
|
|
356
|
+
{@body const groups = [{id:"g1",name:"Review",items:[{id:"a",name:"Alpha"}]}]}
|
|
357
|
+
{#each groups as group}
|
|
358
|
+
<box border padding={3}>
|
|
359
|
+
<title>{group.name}</title>
|
|
360
|
+
{#each group.items as entry,index}
|
|
361
|
+
<text>{index + 1}. {entry.name}</text>
|
|
362
|
+
{/each}
|
|
363
|
+
</box>
|
|
364
|
+
{/each}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Streaming rules:
|
|
368
|
+
|
|
369
|
+
- Append source suffixes while preserving every previous character.
|
|
370
|
+
- Close useful children as they arrive; an enclosing layout may remain open.
|
|
371
|
+
- Leave incomplete tokens pending only while more source will follow.
|
|
372
|
+
- Close an each block before expecting its repeated template to display.
|
|
373
|
+
- End with a complete document; completion drops unfinished tokens and marks the
|
|
374
|
+
answer incomplete.
|
|
375
|
+
- Use callbacks and state for interaction; do not patch earlier streamed source.
|
|
376
|
+
|
|
377
|
+
The parser retains lexical state across chunk boundaries, including quoted strings,
|
|
378
|
+
templates, comments, and regular expressions inside braces. There is no need to
|
|
379
|
+
align transport chunks with tokens. Generation must still produce conventional,
|
|
380
|
+
balanced syntax. Do not count a recoverable partial prefix as valid final output.
|
|
381
|
+
Repeat templates wait for their closing directive so the renderer does not mount
|
|
382
|
+
large numbers of incomplete copies.
|
|
383
|
+
|
|
384
|
+
#### Task: incomplete-stream
|
|
385
|
+
|
|
386
|
+
An unfinished first chunk may be:
|
|
387
|
+
|
|
388
|
+
```text
|
|
389
|
+
<box padding={
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Append `4}><text>Ready</text></box>` and then signal completion. The finished source is:
|
|
393
|
+
|
|
394
|
+
```dil
|
|
395
|
+
<box padding={4}><text>Ready</text></box>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Source replacement, document/message identity changes, and remounting can create a
|
|
399
|
+
new document and reset state. Ordinary suffix appends and virtualized offscreen
|
|
400
|
+
unmounts retain document-owned state. Do not use internal render timing or viewport
|
|
401
|
+
visibility as an authoring lifecycle API.
|
|
402
|
+
|
|
403
|
+
## 3. Component API
|
|
404
|
+
|
|
405
|
+
Read each property block literally. `(optional)` means the property may be omitted;
|
|
406
|
+
`default` describes the widget's current fallback. `(required for generation)`
|
|
407
|
+
means supply a meaningful value even if the permissive renderer has a fallback.
|
|
408
|
+
Defaults do not replace type correctness. A string `"false"` is not boolean false.
|
|
409
|
+
|
|
410
|
+
Children categories: inline = text, inline Markdown, and inline components; generic
|
|
411
|
+
= inline or block content; raw = literal source; none = no content. Named children
|
|
412
|
+
restrict direct child component types. Whitespace and control directives may
|
|
413
|
+
surround named children. These contracts guide generation; the parser is not an
|
|
414
|
+
element-specific schema validator. Do not use parser acceptance as evidence of
|
|
415
|
+
valid browser structure.
|
|
416
|
+
|
|
417
|
+
Shared layout props:
|
|
418
|
+
|
|
419
|
+
```text
|
|
420
|
+
padding: number | {x?:number,y?:number} (optional)
|
|
421
|
+
gap: number (optional)
|
|
422
|
+
radius: "sm" | "md" | "lg" | "xl" | "2xl" | "full" | string (optional)
|
|
423
|
+
border: boolean | {size?:number,color?:string} (optional)
|
|
424
|
+
background: string (optional)
|
|
425
|
+
clip: boolean (optional)
|
|
426
|
+
width: number | string (optional)
|
|
427
|
+
maxWidth: number | string (optional)
|
|
428
|
+
height: number | string (optional)
|
|
429
|
+
flex: number | string (optional)
|
|
430
|
+
columns: number (optional)
|
|
431
|
+
align: string (optional)
|
|
432
|
+
justify: string (optional)
|
|
433
|
+
wrap: "wrap" (optional)
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Only components whose Properties block lists `layout` consume these props. A table
|
|
437
|
+
does not become a layout container merely because table-cell accepts layout props.
|
|
438
|
+
Text, button, input, chart, and other components do not automatically accept them.
|
|
439
|
+
Wrap a component in box/row/grid when the surrounding layout needs control.
|
|
440
|
+
|
|
441
|
+
Numeric padding and gap use four-pixel units: 1=4px, 2=8px, 3=12px, 4=16px.
|
|
442
|
+
An x/y padding object sets inline/block padding independently. It does not accept
|
|
443
|
+
top/right/bottom/left keys. Numeric width, height, and maxWidth are pixels. String
|
|
444
|
+
dimensions may use valid CSS lengths or percentages. Flex follows CSS flex values;
|
|
445
|
+
it is not a width unit. Do not emit numeric strings when a number was intended.
|
|
446
|
+
|
|
447
|
+
Named radii: sm=4px, md=6px, lg=8px, xl=12px, 2xl=16px, full=9999px. A custom
|
|
448
|
+
string radius is passed as a CSS border radius; use a simple valid value. The
|
|
449
|
+
names are DIL names, not assumptions about another design system's scale.
|
|
450
|
+
Border true enables a 1px theme border. An object may change size and color.
|
|
451
|
+
Border false/omitted disables this authored border. Keep widths finite and positive.
|
|
452
|
+
|
|
453
|
+
Use semantic color tokens: default, primary, secondary, tertiary, success, warning,
|
|
454
|
+
danger, surface-secondary, surface-tertiary, subtle, strong. A valid CSS color is
|
|
455
|
+
also accepted when shorter than 128 characters and free of URL/custom-variable
|
|
456
|
+
or declaration syntax. A color object, gradient, arbitrary theme variable, or
|
|
457
|
+
stylesheet string is not accepted. Invalid colors are ignored rather than repaired.
|
|
458
|
+
|
|
459
|
+
Use align start/center/end/stretch for item alignment. Start/end map to flex-start/
|
|
460
|
+
flex-end. Use justify start/center/end/between for common distribution; between
|
|
461
|
+
maps to space-between. The reader accepts strings beyond these recommendations,
|
|
462
|
+
but a browser may reject them. Keep generation to meaningful CSS alignment values.
|
|
463
|
+
Use wrap="wrap" only when the layout benefits from wrapping.
|
|
464
|
+
|
|
465
|
+
Columns sets a responsive grid's requested column count. It is not a general
|
|
466
|
+
child-span/placement API. Use a small positive integer. The stock grid reduces
|
|
467
|
+
columns on narrow screens. A layout prop can be accepted by a shared reader
|
|
468
|
+
without changing a component that does not use the corresponding CSS behavior.
|
|
469
|
+
For example, columns does not turn a row into a grid.
|
|
470
|
+
|
|
471
|
+
### Text components
|
|
472
|
+
|
|
473
|
+
#### Component: text
|
|
474
|
+
|
|
475
|
+
```text
|
|
476
|
+
Properties:
|
|
477
|
+
color: string (optional; inherited color when omitted)
|
|
478
|
+
size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (optional; inherited size)
|
|
479
|
+
weight: "medium" (optional)
|
|
480
|
+
tabularNums: boolean (optional; default false)
|
|
481
|
+
|
|
482
|
+
Children: inline
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Render a span-like text value. Use it for a value inside a row, a short reactive
|
|
486
|
+
sentence, or a styled phrase. Text does not accept layout props, an arbitrary
|
|
487
|
+
style object, href, or a strong prop. Use Markdown emphasis in children when bold
|
|
488
|
+
text is needed. Weight medium maps to 500. Other weight strings do not expose a
|
|
489
|
+
general font-weight API.
|
|
490
|
+
|
|
491
|
+
The size scale is xs=12px, sm=14px, md=16px, lg=18px, xl=24px, 2xl=30px at the
|
|
492
|
+
normal 16px root. tabularNums requests tabular numeral shapes; it does not format
|
|
493
|
+
numbers or align decimal places automatically. Format the expression separately.
|
|
494
|
+
Keep nested content inline; use box for a paragraph containing blocks.
|
|
495
|
+
|
|
496
|
+
```dil
|
|
497
|
+
{@body const revenue = 1234.5}
|
|
498
|
+
<text size="lg" weight="medium" tabularNums>{revenue.toFixed(2)} units</text>
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### Component: title
|
|
502
|
+
|
|
503
|
+
```text
|
|
504
|
+
Properties:
|
|
505
|
+
color: string (optional)
|
|
506
|
+
size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (optional; default lg)
|
|
507
|
+
weight: "medium" (optional; consumed but does not override title weight)
|
|
508
|
+
tabularNums: boolean (optional; default false)
|
|
509
|
+
|
|
510
|
+
Children: inline
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
Render a styled h3 with weight 600, default size 18px, compact line height, and no
|
|
514
|
+
default margin. A weight prop is consumed by the shared text branch but the title
|
|
515
|
+
keeps weight 600. Do not use it to request a different heading rank. For a document
|
|
516
|
+
with h1/h2 hierarchy, use Markdown headings. Use title for a card or panel heading.
|
|
517
|
+
An explicit size can change appearance without changing the heading's rank.
|
|
518
|
+
|
|
519
|
+
Keep controls outside the title; compose title and actions as siblings in a row.
|
|
520
|
+
Do not rely on a title prop to associate it with a dialog, table, or input. Those
|
|
521
|
+
associations are not exposed by the DIL API. Give the surrounding content a clear
|
|
522
|
+
reading order using ordinary source order.
|
|
523
|
+
|
|
524
|
+
#### Component: caption
|
|
525
|
+
|
|
526
|
+
```text
|
|
527
|
+
Properties:
|
|
528
|
+
color: string (optional; default secondary)
|
|
529
|
+
size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (optional; default xs)
|
|
530
|
+
weight: "medium" (optional)
|
|
531
|
+
tabularNums: boolean (optional; default false)
|
|
532
|
+
|
|
533
|
+
Children: inline
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
Render small secondary text, defaulting to 12px. Use it for units, context, helper
|
|
537
|
+
messages, or a short validation message. It is a text span, not a live-region,
|
|
538
|
+
tooltip, accessible description binding, or hidden-label mechanism. Keep messages
|
|
539
|
+
visible and sufficiently descriptive without claiming automatic announcement.
|
|
540
|
+
|
|
541
|
+
Use an explicit danger/warning color only when the text explains the state. A
|
|
542
|
+
red caption alone is not form validation; derive a validity value and guard the
|
|
543
|
+
action. Avoid shrinking essential instructions merely to fit a narrow layout.
|
|
544
|
+
|
|
545
|
+
#### Component: badge
|
|
546
|
+
|
|
547
|
+
```text
|
|
548
|
+
Properties:
|
|
549
|
+
color: string (optional)
|
|
550
|
+
|
|
551
|
+
Children: inline
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
Render a compact status label. Success, warning, and danger colors receive related
|
|
555
|
+
background treatment. Other accepted colors affect foreground but do not create
|
|
556
|
+
arbitrary background variants. There is no variant, size, icon, or onClick prop.
|
|
557
|
+
Place an icon in children when needed and keep visible status text beside it.
|
|
558
|
+
|
|
559
|
+
Do not make a badge look like a selectable control. Use button, checkbox, radio,
|
|
560
|
+
or segmented-control for input. For a changing status, render the badge from state
|
|
561
|
+
or an if directive. Labels such as Saved must reflect an actual supported action;
|
|
562
|
+
copying text is not a saved-server mutation.
|
|
563
|
+
|
|
564
|
+
#### Component: label
|
|
565
|
+
|
|
566
|
+
```text
|
|
567
|
+
Properties: none
|
|
568
|
+
|
|
569
|
+
Children: inline
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Render medium-weight visual label text. It is a styled span and has no for/id
|
|
573
|
+
association props. Pair it with input aria-label using the same visible words.
|
|
574
|
+
Do not claim that clicking this component focuses a separate input. Checkbox and
|
|
575
|
+
radio provide their own clickable label composition through their children.
|
|
576
|
+
|
|
577
|
+
Use label for a compact field heading or a value-group label. It cannot take
|
|
578
|
+
layout, color, or size props. Wrap it in a suitable layout instead of inventing
|
|
579
|
+
styling attributes. Keep the visible label stable while validation messages change.
|
|
580
|
+
|
|
581
|
+
#### Component: CodeBlock
|
|
582
|
+
|
|
583
|
+
```text
|
|
584
|
+
Properties:
|
|
585
|
+
language: string (optional; default empty string)
|
|
586
|
+
editable: boolean (optional; default false)
|
|
587
|
+
|
|
588
|
+
Children: raw
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
Place source directly between opening and closing tags. Everything is literal
|
|
592
|
+
until the exact `</CodeBlock>` delimiter: braces, tags, and directives inside are
|
|
593
|
+
not evaluated. The source prop does not exist. Do not nest DIL components to
|
|
594
|
+
format the source. The display trims leading/trailing whitespace when no draft
|
|
595
|
+
exists, so do not use it for byte-exact whitespace preservation requirements.
|
|
596
|
+
|
|
597
|
+
Editable true exposes an internal text editor. Edits remain local to this widget's
|
|
598
|
+
document draft store. They do not run, update DIL state, call an authored handler,
|
|
599
|
+
or create a downloadable file. There is no onChange/value/defaultValue API. Choose
|
|
600
|
+
input for an authored string value and CodeBlock for editable source presentation.
|
|
601
|
+
|
|
602
|
+
The widget provides copy and word-wrap controls. Copy is user-triggered and can
|
|
603
|
+
fail due to clipboard permissions. Its built-in feedback reports that outcome.
|
|
604
|
+
Do not wrap the code block in another action control or duplicate its copy button
|
|
605
|
+
unless the separate action has a distinct task. Code copying is subject to the
|
|
606
|
+
65,536-character clipboard limit; source display is limited to 131,072 characters.
|
|
607
|
+
|
|
608
|
+
```dil
|
|
609
|
+
<CodeBlock language="javascript" editable>
|
|
610
|
+
const greeting = "Hello";
|
|
611
|
+
console.log(greeting);
|
|
612
|
+
</CodeBlock>
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
Do not include the exact closing delimiter inside its raw source; it terminates
|
|
616
|
+
the component even if it occurs in a quoted source-language string. Use a fenced
|
|
617
|
+
code block for examples that need to show the delimiter literally. Language is a
|
|
618
|
+
display hint, not a compiler selection or permission to execute code.
|
|
619
|
+
|
|
620
|
+
### Media components
|
|
621
|
+
|
|
622
|
+
#### Component: AsyncImage
|
|
623
|
+
|
|
624
|
+
```text
|
|
625
|
+
Properties:
|
|
626
|
+
query: string (required for generation)
|
|
627
|
+
|
|
628
|
+
Children: none
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
Render an offline, locally constructed placeholder illustration with query as
|
|
632
|
+
alt text. The name does not imply remote search, asynchronous model generation,
|
|
633
|
+
or retrieval of a verified image. The stock implementation builds a simple SVG
|
|
634
|
+
landscape; query text only influences a small set of color choices. Do not use it
|
|
635
|
+
as evidence of an actual person, place, product, or event.
|
|
636
|
+
|
|
637
|
+
The placeholder uses a 16:9 wrapper and built-in rounding. There is no src, alt,
|
|
638
|
+
width, height, fit, loading, or onLoad prop. Size the surrounding layout if needed.
|
|
639
|
+
If the browser cannot load the constructed image, the widget displays Image
|
|
640
|
+
unavailable. Do not set your own loaded flag; no authored load callback exists.
|
|
641
|
+
|
|
642
|
+
```dil
|
|
643
|
+
<box maxWidth={480}>
|
|
644
|
+
<AsyncImage query="Placeholder illustration of a mountain landscape"/>
|
|
645
|
+
<caption>Illustrative placeholder, not a photograph.</caption>
|
|
646
|
+
</box>
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
A host may override components under an explicitly supplied contract. That does
|
|
650
|
+
not change the stock contract documented here. Do not assume a host override can
|
|
651
|
+
search the web or load a supplied URL unless the prompt states that capability.
|
|
652
|
+
No stock video, audio player, file preview, or upload component is available.
|
|
653
|
+
|
|
654
|
+
### Layout components
|
|
655
|
+
|
|
656
|
+
#### Component: box
|
|
657
|
+
|
|
658
|
+
```text
|
|
659
|
+
Properties:
|
|
660
|
+
layout
|
|
661
|
+
|
|
662
|
+
Children: generic
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
Use box for vertical flow, panels, and card surfaces. Children retain their source
|
|
666
|
+
order. A box with border/padding/radius/background can present a card without
|
|
667
|
+
inventing a card component. Keep a card's title, body, and actions as readable
|
|
668
|
+
siblings. Set maxWidth when a form or card should remain narrow on a wide screen.
|
|
669
|
+
|
|
670
|
+
Box participates in document flow and may virtualize long child sequences. Do not
|
|
671
|
+
assume every offscreen child is simultaneously mounted. Document state survives
|
|
672
|
+
that presentation behavior. Do not use viewport-dependent expression effects or
|
|
673
|
+
DOM queries to coordinate children. Use declared state and bindings.
|
|
674
|
+
|
|
675
|
+
#### Task: static-card
|
|
676
|
+
|
|
677
|
+
```dil
|
|
678
|
+
<box border padding={4} radius="xl" gap={3} maxWidth={480}>
|
|
679
|
+
<title>Release review</title>
|
|
680
|
+
<text>Ready for the next review.</text>
|
|
681
|
+
<badge color="success">Prepared</badge>
|
|
682
|
+
</box>
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
#### Component: row
|
|
686
|
+
|
|
687
|
+
```text
|
|
688
|
+
Properties:
|
|
689
|
+
layout
|
|
690
|
+
|
|
691
|
+
Children: generic
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
Use row for horizontal siblings such as a title and action, icon and value, or a
|
|
695
|
+
short control group. Set align for vertical alignment and gap for spacing.
|
|
696
|
+
Use wrap="wrap" when labels or controls may exceed available width. Avoid fixed
|
|
697
|
+
heights for rows with wrapping content. A narrow display must retain all controls.
|
|
698
|
+
|
|
699
|
+
Use justify="between" for two groups or spacer for flexible separation. Do not
|
|
700
|
+
insert literal spaces to align components. For multi-column data that needs
|
|
701
|
+
consistent row/cell relationships, use a table rather than independent rows.
|
|
702
|
+
|
|
703
|
+
#### Component: grid
|
|
704
|
+
|
|
705
|
+
```text
|
|
706
|
+
Properties:
|
|
707
|
+
layout
|
|
708
|
+
|
|
709
|
+
Children: generic
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
Use grid for a responsive set of peers. Set columns to a small positive integer
|
|
713
|
+
and gap to the desired spacing unit. The stock grid reduces the requested column
|
|
714
|
+
count to one at viewport widths of 520px or less. Do not compute viewport breakpoints in document
|
|
715
|
+
JavaScript; browser dimensions are not exposed.
|
|
716
|
+
|
|
717
|
+
Generic children are accepted; grid-item is available when a child needs its own
|
|
718
|
+
layout props. There is no template-string API, row-span, column-span, area name,
|
|
719
|
+
or media-query prop. A grid-item does not add a missing placement API. Keep the
|
|
720
|
+
source order meaningful for a single-column reading order.
|
|
721
|
+
|
|
722
|
+
#### Component: grid-item
|
|
723
|
+
|
|
724
|
+
```text
|
|
725
|
+
Properties:
|
|
726
|
+
layout
|
|
727
|
+
|
|
728
|
+
Children: generic
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
Use inside grid when a cell needs padding, border, background, or a nested layout.
|
|
732
|
+
It is a generic layout wrapper and does not expose grid coordinates or spanning.
|
|
733
|
+
The renderer does not require it around every grid child. Avoid a wrapper when
|
|
734
|
+
the child already owns its necessary layout.
|
|
735
|
+
|
|
736
|
+
#### Composition: grid > grid-item
|
|
737
|
+
|
|
738
|
+
```dil
|
|
739
|
+
<grid columns={2} gap={3}>
|
|
740
|
+
<grid-item border padding={3} radius="lg">
|
|
741
|
+
<title>Alpha</title><text>12 sample units</text>
|
|
742
|
+
</grid-item>
|
|
743
|
+
<grid-item border padding={3} radius="lg">
|
|
744
|
+
<title>Beta</title><text>18 sample units</text>
|
|
745
|
+
</grid-item>
|
|
746
|
+
</grid>
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
#### Component: spacer
|
|
750
|
+
|
|
751
|
+
```text
|
|
752
|
+
Properties: none
|
|
753
|
+
|
|
754
|
+
Children: none
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
Use as a flexible child in a row to consume remaining space. It does not accept a
|
|
758
|
+
size, height, width, or direction prop. Use layout gap/padding for fixed spacing.
|
|
759
|
+
An isolated spacer in ordinary vertical content does not promise a fixed blank
|
|
760
|
+
region. Keep spacing intent on the parent whenever possible.
|
|
761
|
+
|
|
762
|
+
#### Component: divider
|
|
763
|
+
|
|
764
|
+
```text
|
|
765
|
+
Properties: none
|
|
766
|
+
|
|
767
|
+
Children: none
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
Render a standard separator. No orientation, thickness, color, or layout props
|
|
771
|
+
are exposed. Use it between meaningful groups rather than after every line.
|
|
772
|
+
Do not place it directly among table rows or radio children; those parents require
|
|
773
|
+
their named child types. Put separation inside a cell/content region if needed.
|
|
774
|
+
|
|
775
|
+
#### Component: table
|
|
776
|
+
|
|
777
|
+
```text
|
|
778
|
+
Properties: none
|
|
779
|
+
|
|
780
|
+
Children: table-row
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
The renderer supplies the body element. Do not emit table-section, tbody, thead,
|
|
784
|
+
tr, td, or th. DIL table has no column sizing, header, dividers, or caption prop.
|
|
785
|
+
Describe the table with nearby text/title and use a first row of readable labels
|
|
786
|
+
when using component cells. For ordinary header semantics and prose-only cells,
|
|
787
|
+
prefer a Markdown table.
|
|
788
|
+
|
|
789
|
+
Keep row widths consistent by generating the same number of cells. There is no
|
|
790
|
+
colSpan or rowSpan. Use a two-column key/value table instead of inventing spanning
|
|
791
|
+
to present irregular data. For empty data, render a caption outside the table
|
|
792
|
+
through a conditional rather than inserting arbitrary text directly into it.
|
|
793
|
+
|
|
794
|
+
#### Component: table-row
|
|
795
|
+
|
|
796
|
+
```text
|
|
797
|
+
Properties: none
|
|
798
|
+
|
|
799
|
+
Children: table-cell
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
Place directly under table, optionally produced by each/if directives. It has no
|
|
803
|
+
selected, header, background, onClick, or layout API. If a row needs an action,
|
|
804
|
+
place a button inside a cell. A pressable cannot replace the structural row.
|
|
805
|
+
Do not wrap rows in box or grid-item under table.
|
|
806
|
+
|
|
807
|
+
#### Component: table-cell
|
|
808
|
+
|
|
809
|
+
```text
|
|
810
|
+
Properties:
|
|
811
|
+
layout
|
|
812
|
+
|
|
813
|
+
Children: generic
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
Place directly under table-row. Cells may contain text, badges, nested layout,
|
|
817
|
+
controls, or a small chart. Layout props style the cell; they do not change table
|
|
818
|
+
structure. There is no align prop with text-alignment semantics beyond the shared
|
|
819
|
+
layout reader, no colSpan/rowSpan, and no header role selection. Use nested rows
|
|
820
|
+
or text formatting only when their actual contract meets the task.
|
|
821
|
+
|
|
822
|
+
#### Composition: table > table-row > table-cell
|
|
823
|
+
|
|
824
|
+
```text
|
|
825
|
+
<table>
|
|
826
|
+
children: table-row
|
|
827
|
+
<table-row>
|
|
828
|
+
children: table-cell
|
|
829
|
+
<table-cell>
|
|
830
|
+
children: generic
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
```dil
|
|
834
|
+
{@body const records = [{id:"a",name:"Alpha",amount:12},{id:"b",name:"Beta",amount:18}]}
|
|
835
|
+
<table>
|
|
836
|
+
<table-row><table-cell><text weight="medium">Name</text></table-cell><table-cell><text weight="medium">Amount</text></table-cell></table-row>
|
|
837
|
+
{#each records as item}
|
|
838
|
+
<table-row><table-cell>{item.name}</table-cell><table-cell><text tabularNums>{item.amount}</text></table-cell></table-row>
|
|
839
|
+
{/each}
|
|
840
|
+
</table>
|
|
841
|
+
```
|
|
842
|
+
|
|
843
|
+
#### Component: popover
|
|
844
|
+
|
|
845
|
+
```text
|
|
846
|
+
Properties: none
|
|
847
|
+
|
|
848
|
+
Children: popover-trigger | popover-content
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
Compose one trigger region and one content region. Open/close behavior belongs to
|
|
852
|
+
the stock overlay. No open/defaultOpen/onOpenChange prop is exposed to DIL. Do not
|
|
853
|
+
add state solely to imitate the existing trigger behavior. Place related optional
|
|
854
|
+
details or controls in the content and keep the triggering label meaningful.
|
|
855
|
+
|
|
856
|
+
#### Component: popover-trigger
|
|
857
|
+
|
|
858
|
+
```text
|
|
859
|
+
Properties: none
|
|
860
|
+
|
|
861
|
+
Children: one button
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
Place exactly one button inside. The trigger context composes that button with
|
|
865
|
+
the overlay behavior; it does not make an arbitrary box or text node a trigger.
|
|
866
|
+
The button can have normal button props. It needs no onClick to open the popover.
|
|
867
|
+
Avoid combining unrelated privileged work with merely opening optional details.
|
|
868
|
+
|
|
869
|
+
#### Component: popover-content
|
|
870
|
+
|
|
871
|
+
```text
|
|
872
|
+
Properties:
|
|
873
|
+
side: "top" | "bottom" (optional; default bottom)
|
|
874
|
+
align: "end" | "center" (optional; default center)
|
|
875
|
+
|
|
876
|
+
Children: generic
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
Place directly under popover. The widget bounds content to the viewport. It has
|
|
880
|
+
no width, padding, layout, modal, placement-offset, or animation prop. Put a box
|
|
881
|
+
inside when the content needs layout. Side values other than top fall back to
|
|
882
|
+
bottom; align values other than end fall back to center. Generate only the stated
|
|
883
|
+
values. Content can contain inputs or actions as siblings in a normal layout.
|
|
884
|
+
|
|
885
|
+
#### Composition: popover > popover-trigger + popover-content
|
|
886
|
+
|
|
887
|
+
```text
|
|
888
|
+
<popover>
|
|
889
|
+
children: popover-trigger | popover-content
|
|
890
|
+
<popover-trigger>
|
|
891
|
+
children: one button
|
|
892
|
+
<popover-content>
|
|
893
|
+
children: generic
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
```dil
|
|
897
|
+
<popover>
|
|
898
|
+
<popover-trigger><button variant="outline">Details</button></popover-trigger>
|
|
899
|
+
<popover-content side="bottom" align="end">
|
|
900
|
+
<box gap={2}><title>Review notes</title><text>No additional action is required.</text></box>
|
|
901
|
+
</popover-content>
|
|
902
|
+
</popover>
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
#### Component: carousel
|
|
906
|
+
|
|
907
|
+
```text
|
|
908
|
+
Properties: none
|
|
909
|
+
|
|
910
|
+
Children: carousel-item
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
Render a horizontal item collection with built-in previous/next controls. Keep
|
|
914
|
+
items as direct children. There is no activeIndex, items data prop, onChange,
|
|
915
|
+
autoplay, orientation, or slide-size API. Do not use it to represent a required
|
|
916
|
+
stepper whose progression must be controlled by validation.
|
|
917
|
+
|
|
918
|
+
#### Component: carousel-item
|
|
919
|
+
|
|
920
|
+
```text
|
|
921
|
+
Properties: none
|
|
922
|
+
|
|
923
|
+
Children: generic
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
Place under carousel. Each slide has a stock width and vertical content wrapper.
|
|
927
|
+
Use a box inside for border/padding/background customization. A carousel-item
|
|
928
|
+
does not accept layout props itself. Keep items understandable independently and
|
|
929
|
+
avoid placing essential instructions only on an undiscovered later slide.
|
|
930
|
+
|
|
931
|
+
#### Composition: carousel > carousel-item
|
|
932
|
+
|
|
933
|
+
```text
|
|
934
|
+
<carousel>
|
|
935
|
+
children: carousel-item
|
|
936
|
+
<carousel-item>
|
|
937
|
+
children: generic
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
```dil
|
|
941
|
+
<carousel>
|
|
942
|
+
<carousel-item><box border padding={4}><title>Alpha</title><text>First option.</text></box></carousel-item>
|
|
943
|
+
<carousel-item><box border padding={4}><title>Beta</title><text>Second option.</text></box></carousel-item>
|
|
944
|
+
</carousel>
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
### Input components
|
|
948
|
+
|
|
949
|
+
#### Component: button
|
|
950
|
+
|
|
951
|
+
```text
|
|
952
|
+
Properties:
|
|
953
|
+
aria-label: string (optional)
|
|
954
|
+
disabled: boolean (optional; default false)
|
|
955
|
+
variant: "outline" | "ghost" | "default" (optional; default default)
|
|
956
|
+
size: "sm" | "xs" | "default" (optional; default default)
|
|
957
|
+
block: boolean (optional; default false)
|
|
958
|
+
onClick: callback () => void (optional)
|
|
959
|
+
|
|
960
|
+
Children: inline
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
Use for explicit actions. Inline children may include icon and text. Give icon-only
|
|
964
|
+
buttons aria-label; keep the name about the action rather than the icon. A label
|
|
965
|
+
fallback exists for some stock source patterns, but generation must provide a
|
|
966
|
+
clear name instead of depending on those demo-oriented fallbacks.
|
|
967
|
+
|
|
968
|
+
Default is a filled action, outline is bordered, and ghost is low-chrome. Unknown
|
|
969
|
+
variant or size strings fall back to default; do not generate unsupported styles.
|
|
970
|
+
Block makes the button full-width. There is no href, type, loading, icon prop,
|
|
971
|
+
layout prop set, or arbitrary DOM event forwarding. Buttons are not form submits.
|
|
972
|
+
|
|
973
|
+
The authored disabled prop and runtime readiness both affect availability. A
|
|
974
|
+
streaming or stopped document may keep a control unavailable even when disabled
|
|
975
|
+
is false. Do not use enabled appearance as proof that an expression has completed.
|
|
976
|
+
Keep handler logic safe independently of a disabled UI guard.
|
|
977
|
+
|
|
978
|
+
```dil
|
|
979
|
+
{@body const [count,setCount] = DIL.useState(0)}
|
|
980
|
+
<button variant="outline" onClick={() => setCount(previous => previous + 1)}>
|
|
981
|
+
<icon name="mouse-pointer-click"/> Increment
|
|
982
|
+
</button>
|
|
983
|
+
<text>{count}</text>
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
#### Component: pressable
|
|
987
|
+
|
|
988
|
+
```text
|
|
989
|
+
Properties:
|
|
990
|
+
layout
|
|
991
|
+
color: string (optional)
|
|
992
|
+
onClick: callback () => void (optional)
|
|
993
|
+
|
|
994
|
+
Children: generic
|
|
995
|
+
```
|
|
996
|
+
|
|
997
|
+
Render a button-like full-card action whose children may include noninteractive
|
|
998
|
+
layout and block content. Keep the action name visible in its content. There is
|
|
999
|
+
no authored aria-label or disabled prop. Do not add them just because the backing
|
|
1000
|
+
element is a browser button. Use button when a task needs authored disabled state.
|
|
1001
|
+
|
|
1002
|
+
Never nest buttons, inputs, radio groups, checkbox, links, or another pressable
|
|
1003
|
+
inside. Place secondary actions beside the pressable, not inside its clickable
|
|
1004
|
+
surface. Layout props apply to the surface; color affects foreground. The widget
|
|
1005
|
+
provides the same action clipboard feedback as button for supported copy actions.
|
|
1006
|
+
|
|
1007
|
+
#### Component: input
|
|
1008
|
+
|
|
1009
|
+
```text
|
|
1010
|
+
Properties:
|
|
1011
|
+
aria-label: string (optional in API; supply for generation)
|
|
1012
|
+
value: string (optional; default empty string)
|
|
1013
|
+
placeholder: string (optional; default empty string)
|
|
1014
|
+
disabled: boolean (optional; default false)
|
|
1015
|
+
onChange: callback (value:string) => void (optional)
|
|
1016
|
+
|
|
1017
|
+
Children: none
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
Use as a single-line string input. Bind value and onChange to document state when
|
|
1021
|
+
other content depends on edits. OnChange receives a string, not a DOM event. There
|
|
1022
|
+
is no type, numeric parsing, email mode, required, pattern, minLength, maxLength,
|
|
1023
|
+
autoComplete, onBlur, or onKeyDown prop. Use explicit string validation and number
|
|
1024
|
+
conversion in derived expressions if the task requires them.
|
|
1025
|
+
|
|
1026
|
+
Placeholder is a hint, not a persistent accessible label. Provide aria-label and,
|
|
1027
|
+
when useful, a sibling label with matching words. The visual label component does
|
|
1028
|
+
not associate itself through an ID. Keep validation messages as visible siblings.
|
|
1029
|
+
|
|
1030
|
+
The widget holds immediate local text drafts while worker updates are acknowledged,
|
|
1031
|
+
including composition input. That does not create a document binding when no
|
|
1032
|
+
onChange/setter exists. Bind state deliberately rather than reading DOM state.
|
|
1033
|
+
Avoid assuming that a local field draft is persisted beyond the document.
|
|
1034
|
+
|
|
1035
|
+
#### Component: slider
|
|
1036
|
+
|
|
1037
|
+
```text
|
|
1038
|
+
Properties:
|
|
1039
|
+
aria-label: string (optional in API; supply for generation)
|
|
1040
|
+
min: number (optional; default 0)
|
|
1041
|
+
max: number (optional; default 100)
|
|
1042
|
+
step: number (optional; default 1)
|
|
1043
|
+
value: number (optional; default 0)
|
|
1044
|
+
marks: {label:string}[] (optional; default no marks)
|
|
1045
|
+
disabled: boolean (optional; default false)
|
|
1046
|
+
onChange: callback (value:number) => void (optional)
|
|
1047
|
+
|
|
1048
|
+
Children: none
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
Use a finite numeric range with min < max and step > 0. Keep value within the
|
|
1052
|
+
range and choose an initial value aligned with the intended step. The widget
|
|
1053
|
+
accepts one numeric value and emits one number; it is not a multi-thumb range
|
|
1054
|
+
control. There is no defaultValue, orientation, tick-value, format, or value-label
|
|
1055
|
+
prop. Show a sibling text value when users need the precise current number.
|
|
1056
|
+
|
|
1057
|
+
Marks are labels distributed along the control. Records do not accept position,
|
|
1058
|
+
value, 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.
|
|
1059
|
+
|
|
1060
|
+
```dil
|
|
1061
|
+
{@body const [level,setLevel] = DIL.useState(40)}
|
|
1062
|
+
<label>Level</label>
|
|
1063
|
+
<slider aria-label="Level" min={0} max={100} step={5} value={level} onChange={setLevel} marks={[{label:"Low"},{label:"High"}]}/>
|
|
1064
|
+
<text tabularNums>{level}%</text>
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
#### Component: checkbox
|
|
1068
|
+
|
|
1069
|
+
```text
|
|
1070
|
+
Properties:
|
|
1071
|
+
checked: boolean (optional; default false)
|
|
1072
|
+
disabled: boolean (optional; default false)
|
|
1073
|
+
lineThrough: boolean (optional; default true)
|
|
1074
|
+
onChange: callback (checked:boolean) => void (optional)
|
|
1075
|
+
|
|
1076
|
+
Children: inline
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
Children provide the visible clickable label. Bind checked/onChange to state for
|
|
1080
|
+
reactive output. The callback receives boolean, not the underlying tri-state API
|
|
1081
|
+
or a DOM event. There is no indeterminate, value, defaultChecked, name, aria-label,
|
|
1082
|
+
or form-submission prop. Use a separate string field only when the task needs it.
|
|
1083
|
+
|
|
1084
|
+
LineThrough controls the checked-label styling. Set it false for settings and
|
|
1085
|
+
consent-style choices; the default suits checklist completion. The label's checked
|
|
1086
|
+
styling uses the bound upstream checked value, while the control can show its
|
|
1087
|
+
immediate draft during worker acknowledgement. Keep binding complete rather than
|
|
1088
|
+
using local draft behavior as a state-management mechanism.
|
|
1089
|
+
|
|
1090
|
+
#### Component: radio-group
|
|
1091
|
+
|
|
1092
|
+
```text
|
|
1093
|
+
Properties:
|
|
1094
|
+
aria-label: string (optional in API; supply for generation)
|
|
1095
|
+
value: string (optional; default empty string)
|
|
1096
|
+
direction: "row" (optional; omitted gives vertical arrangement)
|
|
1097
|
+
onChange: callback (value:string) => void (optional)
|
|
1098
|
+
|
|
1099
|
+
Children: radio
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
Use for one choice among visible options. Bind value/onChange to state and give
|
|
1103
|
+
each radio a unique nonempty string value. Use direction="row" for a wrapping
|
|
1104
|
+
horizontal group. A direction="column" prop is not an additional enum member;
|
|
1105
|
+
omit the prop for vertical. No authored disabled prop exists for the group or
|
|
1106
|
+
its radios. Runtime readiness may disable them while source is incomplete.
|
|
1107
|
+
|
|
1108
|
+
#### Component: radio
|
|
1109
|
+
|
|
1110
|
+
```text
|
|
1111
|
+
Properties:
|
|
1112
|
+
value: string (required for generation)
|
|
1113
|
+
|
|
1114
|
+
Children: inline
|
|
1115
|
+
```
|
|
1116
|
+
|
|
1117
|
+
Place directly under radio-group, possibly through each/if. Children supply the
|
|
1118
|
+
visible label. Selection and callbacks belong to the group; radio has no checked,
|
|
1119
|
+
onChange, disabled, name, or layout props. Do not use a standalone radio outside
|
|
1120
|
+
its required group context.
|
|
1121
|
+
|
|
1122
|
+
#### Composition: radio-group > radio
|
|
1123
|
+
|
|
1124
|
+
```text
|
|
1125
|
+
<radio-group>
|
|
1126
|
+
children: radio
|
|
1127
|
+
<radio>
|
|
1128
|
+
children: inline
|
|
1129
|
+
```
|
|
1130
|
+
|
|
1131
|
+
```dil
|
|
1132
|
+
{@body const [billing,setBilling] = DIL.useState("monthly")}
|
|
1133
|
+
<radio-group aria-label="Billing" value={billing} onChange={setBilling} direction="row">
|
|
1134
|
+
<radio value="monthly">Monthly</radio>
|
|
1135
|
+
<radio value="annual">Annual</radio>
|
|
1136
|
+
</radio-group>
|
|
1137
|
+
<text>Selected: {billing}</text>
|
|
1138
|
+
```
|
|
1139
|
+
|
|
1140
|
+
#### Component: segmented-control
|
|
1141
|
+
|
|
1142
|
+
```text
|
|
1143
|
+
Properties:
|
|
1144
|
+
aria-label: string (optional in API; supply for generation)
|
|
1145
|
+
value: string (optional; default empty string)
|
|
1146
|
+
options: {value:string,label:string}[] (required for generation)
|
|
1147
|
+
onChange: callback (value:string) => void (optional)
|
|
1148
|
+
|
|
1149
|
+
Children: none
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
Use a short array of distinct nonempty string values and readable labels. Bind
|
|
1153
|
+
value/onChange to state. The component emits the selected string, ignoring an
|
|
1154
|
+
empty deselection value. Keep the bound selection among options unless a deliberate
|
|
1155
|
+
initial unselected state is required. It has no multi-select, disabled, option
|
|
1156
|
+
icons, per-option callbacks, or arbitrary child composition.
|
|
1157
|
+
|
|
1158
|
+
Segmented-control selects a value; it is not an authored tabs/panel component.
|
|
1159
|
+
Render content for the selection using if directives. Do not invent tab-panel,
|
|
1160
|
+
onTabChange, or content props. For long choices, prefer radio-group with readable
|
|
1161
|
+
labels rather than crowded segments.
|
|
1162
|
+
|
|
1163
|
+
## 4. Specialized components
|
|
1164
|
+
|
|
1165
|
+
### Data-linked components
|
|
1166
|
+
|
|
1167
|
+
There is no stock query, remote-data, subscription, provider, entity-card, or
|
|
1168
|
+
service-connected component. The supported data-bearing visualization props are
|
|
1169
|
+
Chart.content and NodeGraph.content. Their data shapes are specified under Charts.
|
|
1170
|
+
Ordinary text, tables, and repeated layouts can also display supplied records.
|
|
1171
|
+
None of those components fetches facts based on its label or content keys.
|
|
1172
|
+
|
|
1173
|
+
When the enclosing task supplies data, include the relevant records as literal
|
|
1174
|
+
values in a declaration. Keep only fields needed for the interface. Preserve
|
|
1175
|
+
stable IDs, units, and source labels. If the input is incomplete, show the known
|
|
1176
|
+
fields with an explicit unknown/empty condition rather than fabricating values.
|
|
1177
|
+
Do not infer a remote endpoint from a component name.
|
|
1178
|
+
|
|
1179
|
+
Separate facts from local interaction state. A const record is a good authoring
|
|
1180
|
+
representation of read-only supplied facts; it is not a frozen JavaScript object
|
|
1181
|
+
or an enforced immutable data store. Treat it as read-only by instruction. Use
|
|
1182
|
+
useState for a selected record, draft, filter, or local edit. Do not claim that
|
|
1183
|
+
changing that state updates the original external system.
|
|
1184
|
+
|
|
1185
|
+
#### Task: supplied-data-summary
|
|
1186
|
+
|
|
1187
|
+
```dil
|
|
1188
|
+
{@body const records = [{id:"a",name:"Alpha",amount:12},{id:"b",name:"Beta",amount:18}]}
|
|
1189
|
+
{@body const [query,setQuery] = DIL.useState("")}
|
|
1190
|
+
{@body const visibleRecords = records.filter(item => item.name.toLowerCase().includes(query.toLowerCase()))}
|
|
1191
|
+
{@body const visibleTotal = visibleRecords.reduce((sum,item) => sum + item.amount,0)}
|
|
1192
|
+
<input aria-label="Filter records" value={query} onChange={setQuery}/>
|
|
1193
|
+
<text>{visibleRecords.length} records, {visibleTotal} sample units</text>
|
|
1194
|
+
{#if visibleRecords.length > 0}
|
|
1195
|
+
{#each visibleRecords as item}<text>{item.name}: {item.amount}</text>{/each}
|
|
1196
|
+
{:else}
|
|
1197
|
+
<caption>No matching records.</caption>
|
|
1198
|
+
{/if}
|
|
1199
|
+
```
|
|
1200
|
+
|
|
1201
|
+
The filter transforms supplied data locally. It does not make a search request.
|
|
1202
|
+
Use wording such as Filter records rather than Search the database when no database
|
|
1203
|
+
operation exists. Do not add a refresh button that merely redraws unchanged facts.
|
|
1204
|
+
A reset-filter button can be truthful because it changes local query state.
|
|
1205
|
+
|
|
1206
|
+
### Links and citations
|
|
1207
|
+
|
|
1208
|
+
No stock anchor, citation, reference card, source lookup, footnote resolver, or
|
|
1209
|
+
URL-opening action is available. Markdown recognizes link syntax but displays the
|
|
1210
|
+
label as an inert text span. It does not preserve the URL as a clickable target.
|
|
1211
|
+
Markdown images do not load. The renderer's safe behavior must not be described
|
|
1212
|
+
as browser navigation.
|
|
1213
|
+
|
|
1214
|
+
When a source matters, include its supplied title and visible URL in ordinary text.
|
|
1215
|
+
Keep source numbering local and unambiguous if the input already provides it.
|
|
1216
|
+
Do not invent a bracketed token that implies a host citation registry. A string
|
|
1217
|
+
such as [1] is just text unless the surrounding application provides another
|
|
1218
|
+
explicit contract. Source cards can be composed from box/title/caption, but they
|
|
1219
|
+
remain informational and do not gain privileged behavior.
|
|
1220
|
+
|
|
1221
|
+
#### Task: source-attribution
|
|
1222
|
+
|
|
1223
|
+
```dil
|
|
1224
|
+
<box border padding={3} gap={2}>
|
|
1225
|
+
<title>Supplied source</title>
|
|
1226
|
+
<text>Example release notes</text>
|
|
1227
|
+
<caption>https://example.com/releases</caption>
|
|
1228
|
+
<caption>Reference address shown as text.</caption>
|
|
1229
|
+
</box>
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
If the user requests a navigable link, state the capability limit rather than
|
|
1233
|
+
inventing GenUI.openUrl or window.open. A copy button may copy the supplied URL
|
|
1234
|
+
under the documented clipboard contract. Label that action Copy URL, not Open.
|
|
1235
|
+
Do not automatically copy a URL when displaying its source.
|
|
1236
|
+
|
|
1237
|
+
### Embedded application blocks
|
|
1238
|
+
|
|
1239
|
+
There is no authored iframe, app, embed, script, external widget, plugin frame,
|
|
1240
|
+
browser page, or sandbox block. The renderer's own isolation frame is application
|
|
1241
|
+
infrastructure, not a DIL component that generated source can configure. An
|
|
1242
|
+
interactive dashboard built from supported components remains one DIL document.
|
|
1243
|
+
|
|
1244
|
+
CodeBlock displays or locally edits source. It does not compile an app, install
|
|
1245
|
+
dependencies, execute a preview, create a file, or host a separate application.
|
|
1246
|
+
Do not present its editor as a working code runner. If the task needs a mock
|
|
1247
|
+
application, implement its supported local interactions with state and components
|
|
1248
|
+
and label any unimplemented server behavior accurately.
|
|
1249
|
+
|
|
1250
|
+
Custom components are available only under an explicit host-supplied authoring
|
|
1251
|
+
contract. That contract must establish exact case-sensitive names, property types,
|
|
1252
|
+
children, callback arguments, data boundaries, and any host actions. A demo showing
|
|
1253
|
+
a host component override is not an instruction to generate that component in
|
|
1254
|
+
another document. Do not guess a custom component because the stock vocabulary
|
|
1255
|
+
lacks a desired feature.
|
|
1256
|
+
|
|
1257
|
+
The stock specification validator cannot establish arbitrary custom host semantics.
|
|
1258
|
+
If a host contract exists, validate custom examples against that contract and the
|
|
1259
|
+
real host integration. Keep the distinction visible in the generation instructions.
|
|
1260
|
+
Without such a contract, use only stock components and state the unsupported part.
|
|
1261
|
+
|
|
1262
|
+
## 5. Visualizations
|
|
1263
|
+
|
|
1264
|
+
### Images
|
|
1265
|
+
|
|
1266
|
+
Use AsyncImage under its Media components contract when a placeholder illustration
|
|
1267
|
+
fits the task. It cannot display a supplied photograph URL. Do not put a URL in
|
|
1268
|
+
query and claim the result is the referenced image. Markdown image syntax is
|
|
1269
|
+
suppressed; there is no stock img/src escape hatch.
|
|
1270
|
+
|
|
1271
|
+
For simple authored illustrations, use the presentation-only SVG vocabulary. Put
|
|
1272
|
+
a text description next to the visual and keep important values available as text.
|
|
1273
|
+
SVG is useful for a small static schematic, not a replacement for accessible
|
|
1274
|
+
controls, arbitrary HTML, or a browser canvas application.
|
|
1275
|
+
|
|
1276
|
+
#### Component: svg
|
|
1277
|
+
|
|
1278
|
+
```text
|
|
1279
|
+
Properties:
|
|
1280
|
+
svg props
|
|
1281
|
+
|
|
1282
|
+
Children: SVG elements
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
Shared SVG props:
|
|
1286
|
+
|
|
1287
|
+
```text
|
|
1288
|
+
viewBox: string
|
|
1289
|
+
width: number | string
|
|
1290
|
+
height: number | string
|
|
1291
|
+
x: number | string
|
|
1292
|
+
y: number | string
|
|
1293
|
+
cx: number | string
|
|
1294
|
+
cy: number | string
|
|
1295
|
+
r: number | string
|
|
1296
|
+
rx: number | string
|
|
1297
|
+
ry: number | string
|
|
1298
|
+
d: string
|
|
1299
|
+
fill: string
|
|
1300
|
+
stroke: string
|
|
1301
|
+
strokeWidth: number | string
|
|
1302
|
+
fontSize: number | string
|
|
1303
|
+
fontWeight: number | string
|
|
1304
|
+
opacity: number | string
|
|
1305
|
+
id: string
|
|
1306
|
+
markerWidth: number | string
|
|
1307
|
+
markerHeight: number | string
|
|
1308
|
+
refX: number | string
|
|
1309
|
+
refY: number | string
|
|
1310
|
+
orient: string
|
|
1311
|
+
markerEnd: string
|
|
1312
|
+
```
|
|
1313
|
+
|
|
1314
|
+
All SVG props are optional at the reader boundary; choose the subset required for
|
|
1315
|
+
the selected geometry. Give the root viewBox and practical dimensions so the
|
|
1316
|
+
image is visible and bounded. Use a simple fill/stroke and finite coordinates.
|
|
1317
|
+
SVG strings do not use the DIL semantic-color translation; choose literal safe
|
|
1318
|
+
paint values such as #5e4cff, currentColor, or none where appropriate.
|
|
1319
|
+
|
|
1320
|
+
Allowed SVG elements: svg, defs, marker, path, rect, circle, line, polyline,
|
|
1321
|
+
polygon, g, ellipse, text, tspan, linearGradient, stop. Their names are exact;
|
|
1322
|
+
linearGradient is not linear-gradient. These descendants are recognized only in
|
|
1323
|
+
an SVG subtree. A text tag there is an SVG text element, not the DIL text component.
|
|
1324
|
+
Do not place DIL controls or layouts inside an SVG drawing.
|
|
1325
|
+
|
|
1326
|
+
The attribute allowlist is shared, not a complete per-element SVG schema. A prop
|
|
1327
|
+
being allowed does not mean it has meaning on every element. Use width/height for
|
|
1328
|
+
rect, cx/cy/r for circle, cx/cy/rx/ry for ellipse, and d for path. The allowlist
|
|
1329
|
+
does not expose x1/y1/x2/y2 or points; use path for explicit lines and polygons.
|
|
1330
|
+
Empty line/polyline/polygon elements may parse and render without useful geometry.
|
|
1331
|
+
|
|
1332
|
+
Gradient and stop elements are recognized, but offset, stopColor, gradientUnits,
|
|
1333
|
+
x1/x2, and related full-SVG controls are not exposed. Do not promise an authored
|
|
1334
|
+
multi-stop gradient with this restricted surface. Choose solid paint for reliable
|
|
1335
|
+
illustrations. The examples include these recognized elements to show the actual
|
|
1336
|
+
supported vocabulary and its limits, not to invent the missing attributes.
|
|
1337
|
+
|
|
1338
|
+
SVG values are filtered for dangerous/external strings. External http/data targets,
|
|
1339
|
+
JavaScript URLs, markup-like/declaration strings, and nonlocal URL references are
|
|
1340
|
+
not accepted. Local references such as `url(#arrow)` are supported for paint or
|
|
1341
|
+
marker use. Choose simple document-local IDs containing letters, digits, underscores,
|
|
1342
|
+
or hyphens. Avoid colliding IDs across several authored SVGs in one document.
|
|
1343
|
+
|
|
1344
|
+
There is no href, xlink:href, style, className, transform, event handler, aria-label,
|
|
1345
|
+
role, foreignObject, script, image, a, animate, or arbitrary SVG element/prop API.
|
|
1346
|
+
Do not add them. An SVG element has no onClick bridge and cannot authorize a host
|
|
1347
|
+
action. Use a real button next to the drawing if the user needs an action.
|
|
1348
|
+
|
|
1349
|
+
#### Composition: svg > defs > marker; svg > g > path + text
|
|
1350
|
+
|
|
1351
|
+
```text
|
|
1352
|
+
<svg>
|
|
1353
|
+
children: SVG elements
|
|
1354
|
+
<defs>
|
|
1355
|
+
children: marker | linearGradient
|
|
1356
|
+
<marker>
|
|
1357
|
+
children: SVG shapes
|
|
1358
|
+
<linearGradient>
|
|
1359
|
+
children: stop
|
|
1360
|
+
<g>
|
|
1361
|
+
children: SVG shapes | g | text
|
|
1362
|
+
<text>
|
|
1363
|
+
children: text content | tspan
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
The tree describes useful combinations for generation; it is not a claim that
|
|
1367
|
+
the parser validates a complete SVG content model. Keep definitions in defs,
|
|
1368
|
+
shape groupings in g, and text spans inside text. Use nested tspan only for simple
|
|
1369
|
+
text positioning supported by x/y; there is no dx/dy/textAnchor API.
|
|
1370
|
+
|
|
1371
|
+
```dil
|
|
1372
|
+
<caption>Flow from Alpha to Beta.</caption>
|
|
1373
|
+
<svg viewBox="0 0 320 100" width="100%" height={100}>
|
|
1374
|
+
<defs>
|
|
1375
|
+
<marker id="flow-arrow" markerWidth={10} markerHeight={10} refX={8} refY={3} orient="auto">
|
|
1376
|
+
<path d="M0 0 L8 3 L0 6 Z" fill="#5e4cff"/>
|
|
1377
|
+
</marker>
|
|
1378
|
+
</defs>
|
|
1379
|
+
<g>
|
|
1380
|
+
<rect x={10} y={20} width={90} height={55} rx={8} fill="#eeeeff"/>
|
|
1381
|
+
<rect x={220} y={20} width={90} height={55} rx={8} fill="#eeeeff"/>
|
|
1382
|
+
<path d="M105 47 L210 47" stroke="#5e4cff" strokeWidth={2} markerEnd="url(#flow-arrow)"/>
|
|
1383
|
+
<text x={25} y={52} fontSize={16} fill="#252838">Alpha</text>
|
|
1384
|
+
<text x={235} y={52} fontSize={16} fill="#252838">Beta</text>
|
|
1385
|
+
</g>
|
|
1386
|
+
</svg>
|
|
1387
|
+
```
|
|
1388
|
+
|
|
1389
|
+
### Charts
|
|
1390
|
+
|
|
1391
|
+
Use Chart for quantitative plots, NodeGraph for selectable service-style node
|
|
1392
|
+
diagrams, and Mermaid for declarative diagram text. They have separate contracts;
|
|
1393
|
+
do not combine their content formats. Each is a leaf component. Place a nearby
|
|
1394
|
+
title, units, and summary in normal layout siblings.
|
|
1395
|
+
|
|
1396
|
+
#### Component: Chart
|
|
1397
|
+
|
|
1398
|
+
```text
|
|
1399
|
+
Properties:
|
|
1400
|
+
content: object (required for generation)
|
|
1401
|
+
|
|
1402
|
+
Children: none
|
|
1403
|
+
```
|
|
1404
|
+
|
|
1405
|
+
Line/bar/scatter content:
|
|
1406
|
+
|
|
1407
|
+
```text
|
|
1408
|
+
{
|
|
1409
|
+
chartType: "line" | "bar" | "scatter",
|
|
1410
|
+
data: object[],
|
|
1411
|
+
xKey: string,
|
|
1412
|
+
series: {dataKey:string,label?:string}[]
|
|
1413
|
+
}
|
|
1414
|
+
```
|
|
1415
|
+
|
|
1416
|
+
Pie content:
|
|
1417
|
+
|
|
1418
|
+
```text
|
|
1419
|
+
{
|
|
1420
|
+
chartType: "pie",
|
|
1421
|
+
data: object[],
|
|
1422
|
+
nameKey: string,
|
|
1423
|
+
valueKey: string
|
|
1424
|
+
}
|
|
1425
|
+
```
|
|
1426
|
+
|
|
1427
|
+
Supply chartType explicitly. An absent or unrecognized type currently follows
|
|
1428
|
+
the line rendering branch, but that fallback is not an invitation to generate
|
|
1429
|
+
other names. Only line, bar, scatter, and pie are supported chart types. Do not
|
|
1430
|
+
emit area, radar, bubble, candlestick, heatmap, or composed-chart components.
|
|
1431
|
+
|
|
1432
|
+
Data is an array of plain records. For line/bar, xKey identifies a category or
|
|
1433
|
+
numeric x field; each series dataKey identifies a finite numeric y field. Label
|
|
1434
|
+
is optional and falls back to dataKey. Keep field keys and series keys stable and
|
|
1435
|
+
distinct. Supply units in nearby text rather than inventing axis-formatting props.
|
|
1436
|
+
Do not place React components, functions, or expression strings inside content.
|
|
1437
|
+
|
|
1438
|
+
Scatter uses numeric x data and the first series' dataKey for the shared numeric
|
|
1439
|
+
y-axis configuration. Use one series for the clearest contract. If several series
|
|
1440
|
+
are used, keep numeric fields and units compatible; there is no per-series axis
|
|
1441
|
+
or arbitrary domain configuration. Line/bar may display several series from the
|
|
1442
|
+
same data rows. Missing numeric values are not a defined missing-data policy;
|
|
1443
|
+
preprocess supplied data deliberately and explain unknown values in text.
|
|
1444
|
+
|
|
1445
|
+
Pie uses nameKey for labels and valueKey for quantitative slices. Prefer unique
|
|
1446
|
+
nonempty string names and nonnegative finite values with a positive total. It
|
|
1447
|
+
renders a ring-style pie using stock radii. There is no innerRadius, label
|
|
1448
|
+
formatter, custom sector, selectedSlice, or click callback API.
|
|
1449
|
+
|
|
1450
|
+
Stock chart dimensions, palette, axes, tooltip, marks, and legend are internal.
|
|
1451
|
+
No DIL width/height/layout, color, onSelect, onClick, tooltip, axis, domain, or
|
|
1452
|
+
legend prop is exposed. A wrapper can constrain available width but cannot set a
|
|
1453
|
+
new chart-content schema. Do not infer the full Recharts API from the underlying
|
|
1454
|
+
implementation.
|
|
1455
|
+
|
|
1456
|
+
Multi-series line/bar legends support internal visibility selection. This widget
|
|
1457
|
+
state is not exposed as a DIL binding and does not invoke an authored callback.
|
|
1458
|
+
Scatter and pie legends do not offer the same multi-series selection contract.
|
|
1459
|
+
Hover/focus emphasis is presentation behavior, not data selection available to
|
|
1460
|
+
other document components.
|
|
1461
|
+
|
|
1462
|
+
#### Task: line-chart
|
|
1463
|
+
|
|
1464
|
+
```dil
|
|
1465
|
+
<title>Sample trend</title>
|
|
1466
|
+
<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"}]}}/>
|
|
1467
|
+
<caption>Synthetic units. Actual rises from 10 to 15.</caption>
|
|
1468
|
+
```
|
|
1469
|
+
|
|
1470
|
+
#### Task: pie-chart
|
|
1471
|
+
|
|
1472
|
+
```dil
|
|
1473
|
+
<Chart content={{chartType:"pie",data:[{name:"Alpha",amount:30},{name:"Beta",amount:70}],nameKey:"name",valueKey:"amount"}}/>
|
|
1474
|
+
<caption>Synthetic shares: Alpha 30%, Beta 70%.</caption>
|
|
1475
|
+
```
|
|
1476
|
+
|
|
1477
|
+
When chart data is empty, show an explicit empty-state caption instead of claiming
|
|
1478
|
+
the absence of marks means a zero result. Use a small textual table when values
|
|
1479
|
+
matter more than the visual. Do not fabricate enough points to make a supplied
|
|
1480
|
+
dataset appear more complete. If a transformation drops records, explain why.
|
|
1481
|
+
|
|
1482
|
+
#### Component: NodeGraph
|
|
1483
|
+
|
|
1484
|
+
```text
|
|
1485
|
+
Properties:
|
|
1486
|
+
content: object (required for generation)
|
|
1487
|
+
selectedId: string (optional; no selected node when omitted)
|
|
1488
|
+
onSelect: callback (id:string) => void (optional)
|
|
1489
|
+
|
|
1490
|
+
Children: none
|
|
1491
|
+
```
|
|
1492
|
+
|
|
1493
|
+
Content:
|
|
1494
|
+
|
|
1495
|
+
```text
|
|
1496
|
+
{
|
|
1497
|
+
nodes: {id:string,label:string,sub?:string,x?:number,y?:number}[],
|
|
1498
|
+
edges: {id?:string,source:string,target:string,label?:string}[]
|
|
1499
|
+
}
|
|
1500
|
+
```
|
|
1501
|
+
|
|
1502
|
+
Use unique nonempty string node IDs. Label is the main node text and sub is an
|
|
1503
|
+
optional secondary line. x/y are optional finite positioning hints. Without
|
|
1504
|
+
positions, nodes are arranged in a simple multi-column layout. The renderer
|
|
1505
|
+
adjusts columns and vertical placement to keep nodes readable, so positions are
|
|
1506
|
+
not a pixel-exact canvas contract.
|
|
1507
|
+
|
|
1508
|
+
Edges refer to existing node IDs by source and target. Give edges stable IDs when
|
|
1509
|
+
supplied; otherwise the renderer uses positional IDs. Invalid endpoints are
|
|
1510
|
+
filtered. Only the first 200 nodes and first 400 edges are considered; an edge
|
|
1511
|
+
to a truncated node will not appear. Keep author output within the limits and
|
|
1512
|
+
summarize oversized supplied networks rather than silently claiming full coverage.
|
|
1513
|
+
|
|
1514
|
+
SelectedId controls visible node selection. OnSelect receives the clicked node's
|
|
1515
|
+
string ID. Bind the pair to state if selection should update another panel or
|
|
1516
|
+
remain visibly selected. Without that binding, a callback alone does not update
|
|
1517
|
+
the selectedId prop. There is no selected-node record argument or DOM event.
|
|
1518
|
+
|
|
1519
|
+
Node dragging and connection creation are disabled. Pan/zoom controls are built
|
|
1520
|
+
in; no DIL camera, zoom, connect, drag, edge click, node style, node type, handle,
|
|
1521
|
+
or custom action prop exists. Treat the graph as a navigable selection display,
|
|
1522
|
+
not an editable diagramming application. State changes must use supported callbacks.
|
|
1523
|
+
|
|
1524
|
+
```dil
|
|
1525
|
+
{@body const [selectedId,setSelectedId] = DIL.useState("api")}
|
|
1526
|
+
{@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"}]}}
|
|
1527
|
+
<NodeGraph content={graph} selectedId={selectedId} onSelect={setSelectedId}/>
|
|
1528
|
+
<text>Selected service: {selectedId}</text>
|
|
1529
|
+
```
|
|
1530
|
+
|
|
1531
|
+
#### Component: Mermaid
|
|
1532
|
+
|
|
1533
|
+
```text
|
|
1534
|
+
Properties:
|
|
1535
|
+
source: string (required for generation)
|
|
1536
|
+
|
|
1537
|
+
Children: none
|
|
1538
|
+
```
|
|
1539
|
+
|
|
1540
|
+
Pass Mermaid diagram text as a string expression. A fenced mermaid block is an
|
|
1541
|
+
alternative Markdown representation using the same diagram renderer. Do not put
|
|
1542
|
+
raw children between Mermaid tags; the component reads its source prop only.
|
|
1543
|
+
Use a simple flowchart or another valid Mermaid diagram syntax without app-level
|
|
1544
|
+
configuration.
|
|
1545
|
+
|
|
1546
|
+
The renderer uses strict security, neutral theme, no HTML labels, maximum text
|
|
1547
|
+
size 8,192 characters, and maximum 100 edges. Authored configuration directives,
|
|
1548
|
+
frontmatter at the start, classDef, style/linkStyle lines, click actions, and
|
|
1549
|
+
HTML-like source are rejected. Output is sanitized to remove unsafe SVG content,
|
|
1550
|
+
including links, scripts, and foreignObject. Do not depend on a sanitized link to
|
|
1551
|
+
become navigable.
|
|
1552
|
+
|
|
1553
|
+
Invalid or incomplete source can display a diagram error. Keep Mermaid source
|
|
1554
|
+
small and syntactically complete. There is no authored callback, theme, config,
|
|
1555
|
+
download, source editor, or node-selection API. Use NodeGraph if the task requires
|
|
1556
|
+
supported selection state rather than attempting Mermaid click handlers.
|
|
1557
|
+
|
|
1558
|
+
```dil
|
|
1559
|
+
<Mermaid source={"flowchart LR\n Request --> Review\n Review --> Ready"}/>
|
|
1560
|
+
```
|
|
1561
|
+
|
|
1562
|
+
### Maps
|
|
1563
|
+
|
|
1564
|
+
No map component, map adapter, tiles, geocoder, geographic marker, route engine,
|
|
1565
|
+
or map selection callback exists. Do not emit Map, GeoMap, map, marker, or arbitrary
|
|
1566
|
+
HTML embeds. A node graph is not a geographic coordinate system. SVG can show a
|
|
1567
|
+
small authored schematic, but that does not establish a map-data integration.
|
|
1568
|
+
|
|
1569
|
+
Present supplied places as text, a table, or local filtering over records. Preserve
|
|
1570
|
+
given coordinates as values rather than inventing geocoding results. If location
|
|
1571
|
+
names lack coordinates, do not claim a computed distance or route. Show the
|
|
1572
|
+
capability limit when an interactive map is central to the request.
|
|
1573
|
+
|
|
1574
|
+
#### Task: location-table
|
|
1575
|
+
|
|
1576
|
+
```dil
|
|
1577
|
+
{@body const places = [{id:"berlin",name:"Berlin",latitude:52.52,longitude:13.405}]}
|
|
1578
|
+
<title>Supplied locations</title>
|
|
1579
|
+
<table>
|
|
1580
|
+
{#each places as place}
|
|
1581
|
+
<table-row>
|
|
1582
|
+
<table-cell>{place.name}</table-cell>
|
|
1583
|
+
<table-cell>{place.latitude}, {place.longitude}</table-cell>
|
|
1584
|
+
</table-row>
|
|
1585
|
+
{/each}
|
|
1586
|
+
</table>
|
|
1587
|
+
<caption>Coordinates are shown as supplied; no map or geocoding service is connected.</caption>
|
|
1588
|
+
```
|
|
1589
|
+
|
|
1590
|
+
## 6. Interactivity
|
|
1591
|
+
|
|
1592
|
+
### State management
|
|
1593
|
+
|
|
1594
|
+
Only `DIL.useState(initialValue)` is supported. It is recognized by the declaration
|
|
1595
|
+
syntax and does not expose the React hook object. Use one unique state pair per
|
|
1596
|
+
declaration. A lazy initializer runs when that state name is first initialized.
|
|
1597
|
+
Do not call hooks in interpolation, handler bodies, derived const expressions,
|
|
1598
|
+
conditional branches, or repeated templates.
|
|
1599
|
+
|
|
1600
|
+
Setters accept a replacement value or a function mapping previous state to next
|
|
1601
|
+
state. Use an updater whenever a new value depends on the previous value and
|
|
1602
|
+
several actions may be queued. Keep the updater pure. It may build a new array
|
|
1603
|
+
or object using ordinary JavaScript expressions; do not mutate previous state.
|
|
1604
|
+
|
|
1605
|
+
```dil
|
|
1606
|
+
{@body const [count,setCount] = DIL.useState(0)}
|
|
1607
|
+
<row gap={2} align="center">
|
|
1608
|
+
<button onClick={() => setCount(previous => previous + 1)}>Increment</button>
|
|
1609
|
+
<button variant="outline" onClick={() => setCount(0)}>Reset</button>
|
|
1610
|
+
<text tabularNums>{count}</text>
|
|
1611
|
+
</row>
|
|
1612
|
+
```
|
|
1613
|
+
|
|
1614
|
+
Replace arrays with map/filter/spread and replace changed records with object
|
|
1615
|
+
spread. Mutation such as items.push, record.done=true, or sort in place does not
|
|
1616
|
+
establish the intended setter/dependency contract. Use a copied array before sort.
|
|
1617
|
+
Keep source facts separate from editable state so an agent can tell which values
|
|
1618
|
+
are user drafts.
|
|
1619
|
+
|
|
1620
|
+
State is document-owned. It persists across appends, conditional visibility, and
|
|
1621
|
+
virtualized presentation within that document. A new message/document identity or
|
|
1622
|
+
replacement can reset it. There is no storage or cross-message state API. Do not
|
|
1623
|
+
promise reload persistence, multi-user synchronization, browser-tab sharing, or
|
|
1624
|
+
server write-back.
|
|
1625
|
+
|
|
1626
|
+
Repeated source shares top-level state. Represent per-record edits with an array
|
|
1627
|
+
of records or an object keyed by stable ID. Never create a body declaration inside
|
|
1628
|
+
each expecting an independent state instance. Use the repeated item ID in the
|
|
1629
|
+
handler's immutable update instead.
|
|
1630
|
+
|
|
1631
|
+
#### Task: repeated-record-state
|
|
1632
|
+
|
|
1633
|
+
```dil
|
|
1634
|
+
{@body const [tasks,setTasks] = DIL.useState([{id:"a",label:"Review Alpha",done:false},{id:"b",label:"Review Beta",done:false}])}
|
|
1635
|
+
{@body const completeCount = tasks.filter(task => task.done).length}
|
|
1636
|
+
<text>{completeCount} of {tasks.length} complete</text>
|
|
1637
|
+
{#each tasks as task}
|
|
1638
|
+
<checkbox checked={task.done} onChange={checked => setTasks(previous => previous.map(entry => entry.id === task.id ? {...entry,done:checked} : entry))}>
|
|
1639
|
+
{task.label}
|
|
1640
|
+
</checkbox>
|
|
1641
|
+
{/each}
|
|
1642
|
+
```
|
|
1643
|
+
|
|
1644
|
+
Ordinary const getters are sufficient for derived count, totals, filtered arrays,
|
|
1645
|
+
validity, and selected-record lookup. They are not a caching API. Do not generate
|
|
1646
|
+
useMemo or useCallback to optimize a DIL document. Keep expensive transformations
|
|
1647
|
+
small and reuse a readable binding when it improves correctness.
|
|
1648
|
+
|
|
1649
|
+
Widget-local state has a different contract. Input/slider/checkbox keep immediate
|
|
1650
|
+
drafts while worker callbacks complete. CodeBlock retains editable source drafts.
|
|
1651
|
+
Chart legends hold visibility internally. Popover/carousel maintain their own
|
|
1652
|
+
interaction state. Only documented bindings expose values back to authored DIL.
|
|
1653
|
+
Do not try to read internal widget state through refs, DOM, hidden props, or globals.
|
|
1654
|
+
|
|
1655
|
+
### Event callbacks
|
|
1656
|
+
|
|
1657
|
+
Callback values may be setter references, derived function bindings, or function
|
|
1658
|
+
expressions. Pass the function; do not invoke it while assigning the prop. For
|
|
1659
|
+
example, onChange={setName} is a callback, while onChange={setName("Ada")} performs
|
|
1660
|
+
work during evaluation and does not supply a valid handler.
|
|
1661
|
+
|
|
1662
|
+
#### Callback: button.onClick and pressable.onClick
|
|
1663
|
+
|
|
1664
|
+
Signature: `() => void`. Ignore the undefined argument supplied by the generic
|
|
1665
|
+
invocation path. There is no MouseEvent, target, currentTarget, preventDefault,
|
|
1666
|
+
stopPropagation, or coordinates. Use captured declared values to determine the
|
|
1667
|
+
action. A user activation on these supported action controls can authorize a
|
|
1668
|
+
synchronous GenUI.copy request; arbitrary callbacks do not gain that authority.
|
|
1669
|
+
|
|
1670
|
+
#### Callback: input.onChange
|
|
1671
|
+
|
|
1672
|
+
Signature: `(value:string) => void`. Receive the complete current input string.
|
|
1673
|
+
Use a setter directly for simple controlled input. For a transform, use a function
|
|
1674
|
+
that calls the setter with the transformed value. Keep the value prop a string.
|
|
1675
|
+
Do not read event.target.value or depend on an input-type conversion API.
|
|
1676
|
+
|
|
1677
|
+
#### Callback: slider.onChange
|
|
1678
|
+
|
|
1679
|
+
Signature: `(value:number) => void`. Receive the scalar numeric value, not an array
|
|
1680
|
+
of thumb values or a browser event. Bind the number directly and derive formatted
|
|
1681
|
+
text separately. Do not put a clipboard request in this handler; slider changes
|
|
1682
|
+
are not privileged action-control activations.
|
|
1683
|
+
|
|
1684
|
+
#### Callback: checkbox.onChange
|
|
1685
|
+
|
|
1686
|
+
Signature: `(checked:boolean) => void`. Receive true or false. The underlying UI
|
|
1687
|
+
library's indeterminate representation is normalized; it is not exposed as a DIL
|
|
1688
|
+
value. Bind checked to boolean state. Keep the callback about changing local choice
|
|
1689
|
+
state, and use a separate action button for copying or other explicitly supported
|
|
1690
|
+
privileged work.
|
|
1691
|
+
|
|
1692
|
+
#### Callback: radio-group.onChange and segmented-control.onChange
|
|
1693
|
+
|
|
1694
|
+
Signature: `(value:string) => void`. Receive the selected option's value, not its
|
|
1695
|
+
label or a record. Resolve a record with a derived lookup if the UI needs more
|
|
1696
|
+
fields. Selection does not submit a form. Segmented-control ignores an empty
|
|
1697
|
+
deselection value; do not use empty option strings as ordinary choices.
|
|
1698
|
+
|
|
1699
|
+
#### Callback: NodeGraph.onSelect
|
|
1700
|
+
|
|
1701
|
+
Signature: `(id:string) => void`. Receive the node ID. Bind selectedId to state
|
|
1702
|
+
and derive the selected node from content.nodes if needed. There is no graph
|
|
1703
|
+
event object, coordinates, edge ID, or selection array. Selection callbacks do
|
|
1704
|
+
not authorize clipboard requests.
|
|
1705
|
+
|
|
1706
|
+
Keep callback bodies synchronous and bounded. A callback can update several local
|
|
1707
|
+
state values in order, but it is not a lifecycle effect or an asynchronous task
|
|
1708
|
+
runner. Do not depend on a Promise return value, timer, network response, or host
|
|
1709
|
+
callback completion. State setters have no success receipt available to authored
|
|
1710
|
+
source. Derive updated UI from state, not from guessed render timing.
|
|
1711
|
+
|
|
1712
|
+
Control readiness is managed by the runtime. Open/incomplete source, unresolved
|
|
1713
|
+
expressions, or a stopped document can make controls temporarily unavailable.
|
|
1714
|
+
Do not add a fake loading hook or artificial timer to work around that state.
|
|
1715
|
+
Generate complete source and let the existing renderer manage readiness.
|
|
1716
|
+
|
|
1717
|
+
There are no onSubmit, onInput, onBlur, onFocus, onKeyDown, onLoad, onError,
|
|
1718
|
+
onOpenChange, onValueChange, onDrag, or arbitrary DOM callbacks in the author API.
|
|
1719
|
+
Do not copy underlying React primitive names into DIL. Use the event names listed
|
|
1720
|
+
here, including the capitalized NodeGraph component name.
|
|
1721
|
+
|
|
1722
|
+
#### Task: validation-form
|
|
1723
|
+
|
|
1724
|
+
There is no form tag or browser validation contract. Compose a field, derived
|
|
1725
|
+
validity, visible error text, and guarded action. A disabled button is useful
|
|
1726
|
+
feedback; a handler guard ensures the action itself also checks validity.
|
|
1727
|
+
|
|
1728
|
+
```dil
|
|
1729
|
+
{@body const [name,setName] = DIL.useState("")}
|
|
1730
|
+
{@body const trimmedName = name.trim()}
|
|
1731
|
+
{@body const valid = trimmedName.length >= 2 && trimmedName.length <= 80}
|
|
1732
|
+
<box gap={3} maxWidth={420}>
|
|
1733
|
+
<label>Name</label>
|
|
1734
|
+
<input aria-label="Name" value={name} onChange={setName} placeholder="At least two characters"/>
|
|
1735
|
+
{#if !valid}<caption color="danger">Enter a name between 2 and 80 characters.</caption>{/if}
|
|
1736
|
+
<button disabled={!valid} onClick={() => { if (valid) GenUI.copy(trimmedName); }}>Copy name</button>
|
|
1737
|
+
</box>
|
|
1738
|
+
```
|
|
1739
|
+
|
|
1740
|
+
This copies a valid local draft. It does not submit, save, create a user, or email
|
|
1741
|
+
anyone. If the requested outcome requires an absent host action, state that limit
|
|
1742
|
+
and do not substitute a misleading success message. Do not call the copy result
|
|
1743
|
+
a successful form submission.
|
|
1744
|
+
|
|
1745
|
+
### Data bindings
|
|
1746
|
+
|
|
1747
|
+
There is no predefined external-data variable, provider registry, props object,
|
|
1748
|
+
context hook, request result, subscription, or remote mutation API. Embed supplied
|
|
1749
|
+
JSON-compatible records in a top-level const declaration. A host can supply a
|
|
1750
|
+
separate custom contract, but stock generated source must not guess one.
|
|
1751
|
+
|
|
1752
|
+
Read fields with dot access, optional chaining, and computed keys. Use pure array
|
|
1753
|
+
and string operations to transform data for display. Computed property names are
|
|
1754
|
+
supported JavaScript expressions, not a remote query language. Only access fields
|
|
1755
|
+
present in the supplied data or created by the document. Use explicit null/empty
|
|
1756
|
+
checks when the input permits absent values.
|
|
1757
|
+
|
|
1758
|
+
Use const bindings as read-only source facts by instruction. This is not an
|
|
1759
|
+
enforced Object.freeze guarantee. Use state for drafts and preserve source IDs.
|
|
1760
|
+
Do not change source data in place to imitate a two-way binding. A state change
|
|
1761
|
+
updates dependent expressions; it does not write back to an external origin.
|
|
1762
|
+
|
|
1763
|
+
Binding scope:
|
|
1764
|
+
|
|
1765
|
+
| Binding | Visible where | Lifetime |
|
|
1766
|
+
| --------------------- | ----------------------------------------------------------- | --------------------------- |
|
|
1767
|
+
| Top-level const/state | Same document's expressions and callbacks | Mounted document |
|
|
1768
|
+
| each item/index | Rendered subtree of that iteration, including nested scopes | Corresponding item instance |
|
|
1769
|
+
| Callback parameter | Its function body | Callback invocation |
|
|
1770
|
+
| Code editor draft | Internal CodeBlock only | Document draft identity |
|
|
1771
|
+
| Chart legend state | Internal Chart only | Widget presentation state |
|
|
1772
|
+
|
|
1773
|
+
A body declaration is always document-scoped and never captures a loop binding.
|
|
1774
|
+
An event function expression inside a repeated rendered subtree can capture its
|
|
1775
|
+
item/index scope. Use the stable item ID in updates rather than a potentially
|
|
1776
|
+
stale position. Keep source declarations outside the repeated template.
|
|
1777
|
+
|
|
1778
|
+
```dil
|
|
1779
|
+
{@body const supplied = [{id:"a",name:"Alpha",amount:12},{id:"b",name:"Beta",amount:18}]}
|
|
1780
|
+
{@body const [selected,setSelected] = DIL.useState("a")}
|
|
1781
|
+
{@body const current = supplied.find(item => item.id === selected)}
|
|
1782
|
+
{#each supplied as item}
|
|
1783
|
+
<button variant="outline" onClick={() => setSelected(item.id)}>{item.name}</button>
|
|
1784
|
+
{/each}
|
|
1785
|
+
{#if current}<text>{current["name"]}: {current.amount}</text>{:else}<caption>No selection.</caption>{/if}
|
|
1786
|
+
```
|
|
1787
|
+
|
|
1788
|
+
Use the same principle for chart data: derive a plain content object or use bound
|
|
1789
|
+
arrays within content. The chart does not subscribe to the originating dataset;
|
|
1790
|
+
it re-renders from the supplied prop. An empty array is an empty dataset, not a
|
|
1791
|
+
loading indication. Loading and failed-request states require explicit supplied
|
|
1792
|
+
facts or a separate host contract; do not fabricate asynchronous phases.
|
|
1793
|
+
|
|
1794
|
+
### Host actions
|
|
1795
|
+
|
|
1796
|
+
Only `GenUI.copy(text:string): undefined` is exposed. It requests a clipboard
|
|
1797
|
+
write of at most 65,536 characters. It does not read the clipboard or create a
|
|
1798
|
+
file. Pass an actual string; serialize records deliberately if the requested
|
|
1799
|
+
task is to copy JSON. A nonempty request is required for a dispatched copy;
|
|
1800
|
+
empty text currently produces no clipboard operation.
|
|
1801
|
+
|
|
1802
|
+
Invoke copy synchronously in a button or pressable onClick after explicit user
|
|
1803
|
+
activation. The renderer carries an action intent through the host boundary and
|
|
1804
|
+
associates the clipboard outcome with that initiating control. A valid-looking
|
|
1805
|
+
call in initialization, interpolation, a getter, a value-change handler, or a
|
|
1806
|
+
node-selection callback cannot confer the required authorization.
|
|
1807
|
+
|
|
1808
|
+
Do not defer copy through Promise.then, async/await, timers, or an automatic
|
|
1809
|
+
effect. Those are not documented action paths. Do not forge internal receipt or
|
|
1810
|
+
gesture fields. Copy authorization and browser/platform permission are separate:
|
|
1811
|
+
the platform can deny a correctly invoked request.
|
|
1812
|
+
|
|
1813
|
+
```dil
|
|
1814
|
+
{@body const report = "Review complete: Alpha and Beta checked."}
|
|
1815
|
+
<button onClick={() => GenUI.copy(report)}><icon name="copy"/> Copy report</button>
|
|
1816
|
+
```
|
|
1817
|
+
|
|
1818
|
+
Call once per action. The VM tracks one copy value for an execution; several copy
|
|
1819
|
+
calls do not establish an ordered batch of clipboard writes. Keep the requested
|
|
1820
|
+
payload below the limit and construct it before invocation with a pure binding.
|
|
1821
|
+
If copying a selected record, validate that selection exists in the handler.
|
|
1822
|
+
|
|
1823
|
+
The call returns undefined. It is not a Promise and does not return success or
|
|
1824
|
+
failure to authored source. Do not branch on its return value or set copied=true
|
|
1825
|
+
immediately after calling it. Button/pressable display Copied or Copy failed using
|
|
1826
|
+
the actual host outcome. CodeBlock's built-in copy control has its own feedback.
|
|
1827
|
+
Use that behavior rather than duplicate success flags or guessed timeouts.
|
|
1828
|
+
|
|
1829
|
+
Clipboard denial should leave the existing content and local draft available.
|
|
1830
|
+
Users can retry the same explicit action after resolving platform permissions.
|
|
1831
|
+
Do not clear the input merely because copy was requested. Do not promise a
|
|
1832
|
+
clipboard read-back or automatic retry; neither is an author API.
|
|
1833
|
+
|
|
1834
|
+
Unsupported host operations include openUrl, issueNewTurn, download, export,
|
|
1835
|
+
file creation, printing, network requests, storage, browser navigation, arbitrary
|
|
1836
|
+
postMessage, and server mutations. Mention an unavailable capability when it is
|
|
1837
|
+
essential to the requested task. Never replace it with an invented GenUI method.
|
|
1838
|
+
The renderer's own transport and widget-internal browser calls are not privileges
|
|
1839
|
+
granted to authored expressions.
|
|
1840
|
+
|
|
1841
|
+
#### Task: host-action-review
|
|
1842
|
+
|
|
1843
|
+
Check the control, event, payload type, payload length, and execution timing.
|
|
1844
|
+
A copy button with a string payload and synchronous onClick is supported. A
|
|
1845
|
+
slider onChange that calls copy, a const getter that calls copy while rendering,
|
|
1846
|
+
or an automatic initialization call is unsupported even if the text is harmless.
|
|
1847
|
+
Keep copy requests intentional and visible to the person activating the control.
|
|
1848
|
+
|
|
1849
|
+
## 7. Assets
|
|
1850
|
+
|
|
1851
|
+
### Icons
|
|
1852
|
+
|
|
1853
|
+
#### Component: icon
|
|
1854
|
+
|
|
1855
|
+
```text
|
|
1856
|
+
Properties:
|
|
1857
|
+
name: string (required for generation)
|
|
1858
|
+
size: "xs" | "lg" (optional; default 17px)
|
|
1859
|
+
color: string (optional)
|
|
1860
|
+
|
|
1861
|
+
Children: none
|
|
1862
|
+
```
|
|
1863
|
+
|
|
1864
|
+
Supported names:
|
|
1865
|
+
|
|
1866
|
+
```text
|
|
1867
|
+
chart-no-axes-combined
|
|
1868
|
+
circle-check
|
|
1869
|
+
check-circle-2
|
|
1870
|
+
circle
|
|
1871
|
+
wallet
|
|
1872
|
+
trending-up
|
|
1873
|
+
users
|
|
1874
|
+
rotate-ccw
|
|
1875
|
+
copy
|
|
1876
|
+
sliders-horizontal
|
|
1877
|
+
ellipsis
|
|
1878
|
+
sparkles
|
|
1879
|
+
mouse-pointer-click
|
|
1880
|
+
x
|
|
1881
|
+
git-merge
|
|
1882
|
+
package-check
|
|
1883
|
+
shield-check
|
|
1884
|
+
settings-2
|
|
1885
|
+
info
|
|
1886
|
+
code-2
|
|
1887
|
+
alert-triangle
|
|
1888
|
+
```
|
|
1889
|
+
|
|
1890
|
+
Use exactly these names. An unknown name falls back to circle, which can conceal
|
|
1891
|
+
a generation mistake rather than raise an error. Do not request an external
|
|
1892
|
+
Lucide name because the renderer internally uses Lucide. The allowlist is the
|
|
1893
|
+
author API. There is no arbitrary SVG path, icon URL, upload, sprite, or library
|
|
1894
|
+
import prop.
|
|
1895
|
+
|
|
1896
|
+
Size xs=13px, omitted=17px, lg=22px. There is no explicit md size enum; omit size
|
|
1897
|
+
for the normal icon. Color uses the same semantic token/CSS color reader as DIL
|
|
1898
|
+
text. It does not accept a CSS class, style object, or custom variable. Icons are
|
|
1899
|
+
inline decorative elements; put them beside meaningful text.
|
|
1900
|
+
|
|
1901
|
+
Icons are aria-hidden in the stock renderer. They cannot carry an authored
|
|
1902
|
+
aria-label or title prop. An icon-only button needs its own aria-label. A badge
|
|
1903
|
+
or status line needs visible words even when its icon seems recognizable. Do not
|
|
1904
|
+
communicate critical state using icon shape/color alone.
|
|
1905
|
+
|
|
1906
|
+
#### Composition: button > icon + inline text
|
|
1907
|
+
|
|
1908
|
+
```dil
|
|
1909
|
+
<button onClick={() => GenUI.copy("Review complete")}>
|
|
1910
|
+
<icon name="copy" size="xs"/> Copy review
|
|
1911
|
+
</button>
|
|
1912
|
+
```
|
|
1913
|
+
|
|
1914
|
+
#### Composition: button > icon with accessible action name
|
|
1915
|
+
|
|
1916
|
+
```dil
|
|
1917
|
+
{@body const [count,setCount] = DIL.useState(0)}
|
|
1918
|
+
<button aria-label="Reset count" variant="ghost" onClick={() => setCount(0)}>
|
|
1919
|
+
<icon name="rotate-ccw"/>
|
|
1920
|
+
</button>
|
|
1921
|
+
<text>{count}</text>
|
|
1922
|
+
```
|
|
1923
|
+
|
|
1924
|
+
Use the example catalog's icon gallery to locate all allowed names. Icons do not
|
|
1925
|
+
create host operations: a download-looking symbol would not add a download API,
|
|
1926
|
+
and the copy icon itself has no onClick. Put the supported action on the containing
|
|
1927
|
+
button or pressable and obey the host-action contract.
|