@ouispec/contract 0.1.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/INTEGRATOR-GUIDE.md +729 -0
- package/LICENSE +21 -0
- package/README.md +10 -0
- package/dist/codegen.d.ts +71 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +195 -0
- package/dist/codegen.js.map +1 -0
- package/dist/generated/contract.d.ts +1286 -0
- package/dist/generated/contract.d.ts.map +1 -0
- package/dist/generated/contract.js +14 -0
- package/dist/generated/contract.js.map +1 -0
- package/dist/generated/schemas.d.ts +111 -0
- package/dist/generated/schemas.d.ts.map +1 -0
- package/dist/generated/schemas.js +3256 -0
- package/dist/generated/schemas.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/render-contract.d.ts +47 -0
- package/dist/render-contract.d.ts.map +1 -0
- package/dist/render-contract.js +123 -0
- package/dist/render-contract.js.map +1 -0
- package/dist/render-guide.d.ts +4 -0
- package/dist/render-guide.d.ts.map +1 -0
- package/dist/render-guide.js +132 -0
- package/dist/render-guide.js.map +1 -0
- package/dist/schema-document.d.ts +7 -0
- package/dist/schema-document.d.ts.map +1 -0
- package/dist/schema-document.js +2 -0
- package/dist/schema-document.js.map +1 -0
- package/dist/validate.d.ts +22 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +89 -0
- package/dist/validate.js.map +1 -0
- package/package.json +65 -0
- package/schemas/action-effect.json +113 -0
- package/schemas/agent-binding.json +58 -0
- package/schemas/approvals.json +249 -0
- package/schemas/control-kind-registration.json +187 -0
- package/schemas/control-table.json +276 -0
- package/schemas/event-declarations.json +316 -0
- package/schemas/generated-knowledge.json +58 -0
- package/schemas/json-schema.json +153 -0
- package/schemas/oui-config.json +178 -0
- package/schemas/oui-manifest.json +346 -0
- package/schemas/room-catalog-data.json +455 -0
- package/schemas/tier2-mapping.json +195 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.closurestudio.ai/oui/v1/room-catalog-data.json",
|
|
4
|
+
"title": "RoomCatalogData",
|
|
5
|
+
"description": "A room catalog as plain data (ADR-0220 §2.3, tier 3 of ADR-0226): what a room with its own editing model — a canvas, a chart, a timeline, a player — declares about everything a person can do in it, so the assistant's actions and knowledge are generated from the room's code. Every declaration, none of the functions: a room's package writes it as `agent-catalog.json` (named in `package.json` under `oui.agentCatalog`) so a build-time generator reads the catalog without loading React or the room's code; an app's own catalog is read through the app's Vite config.\n\n- **actions**: its operations, each carried out through the room's own reducer and commands, with a JSON schema for the input;\n- **fields**: its inspector's fields, each with its value's schema, unit, range, its animation where the room has a timeline, and which kinds of thing it applies to;\n- **commands**: its keymap, each command with its keys and what it does;\n- **observations**: what the host reports about the room's state, including the problems it has drawing it.\n\nA room derives each action's input from the schema its reducer already validates with (`z.toJSONSchema`) and re-checks input with the same schema before applying it.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"room": {
|
|
9
|
+
"description": "The room's id: the surface id its assistant surface is published under (`room:<id>`).",
|
|
10
|
+
"type": "string",
|
|
11
|
+
"minLength": 1
|
|
12
|
+
},
|
|
13
|
+
"title": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"minLength": 1
|
|
16
|
+
},
|
|
17
|
+
"description": {
|
|
18
|
+
"description": "What the room is for, in one or two sentences.",
|
|
19
|
+
"type": "string",
|
|
20
|
+
"minLength": 1
|
|
21
|
+
},
|
|
22
|
+
"actions": {
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": {
|
|
25
|
+
"$ref": "#/$defs/RoomActionData"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"fields": {
|
|
29
|
+
"type": "array",
|
|
30
|
+
"items": {
|
|
31
|
+
"$ref": "#/$defs/RoomFieldData"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"commands": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"items": {
|
|
37
|
+
"$ref": "#/$defs/RoomCommand"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"observations": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"items": {
|
|
43
|
+
"$ref": "#/$defs/RoomObservation"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"problems": {
|
|
47
|
+
"description": "The kinds of problem it reports, in its own vocabulary. Default: the generic `problems` schema.",
|
|
48
|
+
"type": "array",
|
|
49
|
+
"items": {
|
|
50
|
+
"$ref": "#/$defs/RoomProblemKind"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"recipes": {
|
|
54
|
+
"description": "Tasks its tools carry out together, which only the room knows.",
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": {
|
|
57
|
+
"$ref": "#/$defs/RoomRecipe"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"required": [
|
|
62
|
+
"room",
|
|
63
|
+
"title",
|
|
64
|
+
"description",
|
|
65
|
+
"actions",
|
|
66
|
+
"fields",
|
|
67
|
+
"commands",
|
|
68
|
+
"observations"
|
|
69
|
+
],
|
|
70
|
+
"additionalProperties": false,
|
|
71
|
+
"$defs": {
|
|
72
|
+
"RoomEntryInfo": {
|
|
73
|
+
"description": "What every catalog entry says about itself. Knowledge is generated from these words alone.",
|
|
74
|
+
"type": "object",
|
|
75
|
+
"properties": {
|
|
76
|
+
"id": {
|
|
77
|
+
"description": "Stable, kebab-case, unique among the room's entries of its kind.",
|
|
78
|
+
"type": "string",
|
|
79
|
+
"minLength": 1
|
|
80
|
+
},
|
|
81
|
+
"title": {
|
|
82
|
+
"description": "What the UI calls it: a button's label, a field's label, a command's name.",
|
|
83
|
+
"type": "string"
|
|
84
|
+
},
|
|
85
|
+
"description": {
|
|
86
|
+
"description": "What it does, in a sentence or two, in the room's own terms.",
|
|
87
|
+
"type": "string"
|
|
88
|
+
},
|
|
89
|
+
"control": {
|
|
90
|
+
"description": "Where a person does it: the tool, panel, button, key or gesture.",
|
|
91
|
+
"type": "string"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"required": [
|
|
95
|
+
"id",
|
|
96
|
+
"title",
|
|
97
|
+
"description",
|
|
98
|
+
"control"
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
"RoomActionData": {
|
|
102
|
+
"description": "One operation of the room, without its `run`.",
|
|
103
|
+
"type": "object",
|
|
104
|
+
"allOf": [
|
|
105
|
+
{
|
|
106
|
+
"$ref": "#/$defs/RoomEntryInfo"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"type": "object",
|
|
110
|
+
"properties": {
|
|
111
|
+
"kind": {
|
|
112
|
+
"const": "action"
|
|
113
|
+
},
|
|
114
|
+
"input": {
|
|
115
|
+
"description": "An object schema: a tool's input is one, never a union at its top level. Its property descriptions are the parameters' documentation.",
|
|
116
|
+
"$ref": "json-schema.json"
|
|
117
|
+
},
|
|
118
|
+
"effect": {
|
|
119
|
+
"description": "What it changes: the document (`edit`), the selection, the view, files, backend data, a job, a transaction.",
|
|
120
|
+
"$ref": "action-effect.json"
|
|
121
|
+
},
|
|
122
|
+
"destructive": {
|
|
123
|
+
"description": "It removes or replaces something the person made; running it needs the person's approval (ADR-0228).",
|
|
124
|
+
"type": "boolean"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"required": [
|
|
128
|
+
"kind",
|
|
129
|
+
"input",
|
|
130
|
+
"effect"
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"unevaluatedProperties": false
|
|
135
|
+
},
|
|
136
|
+
"RoomSection": {
|
|
137
|
+
"description": "Which inspector section a field is in, as the inspector titles it.",
|
|
138
|
+
"type": "object",
|
|
139
|
+
"properties": {
|
|
140
|
+
"id": {
|
|
141
|
+
"type": "string"
|
|
142
|
+
},
|
|
143
|
+
"title": {
|
|
144
|
+
"type": "string"
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"required": [
|
|
148
|
+
"id",
|
|
149
|
+
"title"
|
|
150
|
+
],
|
|
151
|
+
"additionalProperties": false
|
|
152
|
+
},
|
|
153
|
+
"RoomFieldAnimation": {
|
|
154
|
+
"description": "A field's animation, in a room with a timeline. Animation is a capability, not a requirement (ADR-0226 §2.6).",
|
|
155
|
+
"type": "object",
|
|
156
|
+
"properties": {
|
|
157
|
+
"keyframeable": {
|
|
158
|
+
"description": "Set at the playhead, it is a keyframe there when the property is animated.",
|
|
159
|
+
"type": "boolean"
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"required": [
|
|
163
|
+
"keyframeable"
|
|
164
|
+
],
|
|
165
|
+
"additionalProperties": false
|
|
166
|
+
},
|
|
167
|
+
"RoomFieldData": {
|
|
168
|
+
"description": "One inspector field, without its `read` and `write`: what it shows for the selection, and what setting it does.",
|
|
169
|
+
"type": "object",
|
|
170
|
+
"allOf": [
|
|
171
|
+
{
|
|
172
|
+
"$ref": "#/$defs/RoomEntryInfo"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"type": "object",
|
|
176
|
+
"properties": {
|
|
177
|
+
"kind": {
|
|
178
|
+
"const": "field"
|
|
179
|
+
},
|
|
180
|
+
"section": {
|
|
181
|
+
"$ref": "#/$defs/RoomSection"
|
|
182
|
+
},
|
|
183
|
+
"appliesTo": {
|
|
184
|
+
"description": "The kinds of thing it applies to, in the room's vocabulary (`text`, `shape`, `artboard`…).",
|
|
185
|
+
"type": "array",
|
|
186
|
+
"items": {
|
|
187
|
+
"type": "string"
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"value": {
|
|
191
|
+
"description": "The value's schema: its type, range (`minimum`/`maximum`), options (`enum`) and unit (`x-unit`).",
|
|
192
|
+
"$ref": "json-schema.json"
|
|
193
|
+
},
|
|
194
|
+
"animation": {
|
|
195
|
+
"description": "How it animates, in a room with a timeline. A room without one leaves it out.",
|
|
196
|
+
"$ref": "#/$defs/RoomFieldAnimation"
|
|
197
|
+
},
|
|
198
|
+
"keyframeable": {
|
|
199
|
+
"description": "Deprecated since oui-bindings 0.8: `animation: { keyframeable }`. Read for one minor.",
|
|
200
|
+
"type": "boolean"
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
"required": [
|
|
204
|
+
"kind",
|
|
205
|
+
"section",
|
|
206
|
+
"appliesTo",
|
|
207
|
+
"value"
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
],
|
|
211
|
+
"unevaluatedProperties": false
|
|
212
|
+
},
|
|
213
|
+
"RoomCommand": {
|
|
214
|
+
"description": "One keymap command: what its key does.",
|
|
215
|
+
"type": "object",
|
|
216
|
+
"allOf": [
|
|
217
|
+
{
|
|
218
|
+
"$ref": "#/$defs/RoomEntryInfo"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"type": "object",
|
|
222
|
+
"properties": {
|
|
223
|
+
"kind": {
|
|
224
|
+
"const": "command"
|
|
225
|
+
},
|
|
226
|
+
"group": {
|
|
227
|
+
"description": "The group the room lists it under: tools, objects, edit, view.",
|
|
228
|
+
"type": "string"
|
|
229
|
+
},
|
|
230
|
+
"keys": {
|
|
231
|
+
"description": "Its keys as a person reads them (`⇧⌘G`). Empty when it has none.",
|
|
232
|
+
"type": "array",
|
|
233
|
+
"items": {
|
|
234
|
+
"type": "string"
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"status": {
|
|
238
|
+
"description": "`reserved`: its key is kept for a feature that is not built; it does nothing. Never offered.",
|
|
239
|
+
"enum": [
|
|
240
|
+
"available",
|
|
241
|
+
"reserved"
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
"options": {
|
|
245
|
+
"description": "Options the command takes beyond the selection (a nudge's direction).",
|
|
246
|
+
"$ref": "json-schema.json"
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
"required": [
|
|
250
|
+
"kind",
|
|
251
|
+
"group",
|
|
252
|
+
"keys",
|
|
253
|
+
"status"
|
|
254
|
+
]
|
|
255
|
+
}
|
|
256
|
+
],
|
|
257
|
+
"unevaluatedProperties": false
|
|
258
|
+
},
|
|
259
|
+
"RoomObservation": {
|
|
260
|
+
"description": "Something the room reports about its state: the document, what is selected, or the problems it has drawing it. The host pushes the value; the catalog declares what it means.",
|
|
261
|
+
"type": "object",
|
|
262
|
+
"properties": {
|
|
263
|
+
"id": {
|
|
264
|
+
"type": "string",
|
|
265
|
+
"minLength": 1
|
|
266
|
+
},
|
|
267
|
+
"description": {
|
|
268
|
+
"type": "string"
|
|
269
|
+
},
|
|
270
|
+
"schema": {
|
|
271
|
+
"$ref": "json-schema.json"
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
"required": [
|
|
275
|
+
"id",
|
|
276
|
+
"description",
|
|
277
|
+
"schema"
|
|
278
|
+
],
|
|
279
|
+
"additionalProperties": false
|
|
280
|
+
},
|
|
281
|
+
"RoomProblemKind": {
|
|
282
|
+
"description": "One kind of problem a room or page reports, in its own vocabulary (`missing-font`, `order-rejected`): the kind, and what it means.",
|
|
283
|
+
"type": "object",
|
|
284
|
+
"properties": {
|
|
285
|
+
"kind": {
|
|
286
|
+
"type": "string",
|
|
287
|
+
"minLength": 1
|
|
288
|
+
},
|
|
289
|
+
"description": {
|
|
290
|
+
"type": "string",
|
|
291
|
+
"minLength": 1
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
"required": [
|
|
295
|
+
"kind",
|
|
296
|
+
"description"
|
|
297
|
+
],
|
|
298
|
+
"additionalProperties": false
|
|
299
|
+
},
|
|
300
|
+
"RoomRecipe": {
|
|
301
|
+
"description": "A task the room's own tools carry out together, declared by the room because only it knows the task (animating a property, placing an order). The generator turns it into a knowledge recipe and ends it with reading what the room reports.\n\nIn `name`, `trigger` and each step, `{room}` is the room's title, and these name the tool that does a step, checked against the catalog when the knowledge is generated:\n- `{action:<id>}`: the action's tool;\n- `{command:<id>}`: the command, run with the `run-command` action;\n- `{field:<id>}`: the field, set with the `set-properties` action;\n- `{keyframeable}`: the ids of the fields that animate.",
|
|
302
|
+
"type": "object",
|
|
303
|
+
"properties": {
|
|
304
|
+
"name": {
|
|
305
|
+
"type": "string",
|
|
306
|
+
"minLength": 1
|
|
307
|
+
},
|
|
308
|
+
"trigger": {
|
|
309
|
+
"type": "string",
|
|
310
|
+
"minLength": 1
|
|
311
|
+
},
|
|
312
|
+
"steps": {
|
|
313
|
+
"type": "array",
|
|
314
|
+
"items": {
|
|
315
|
+
"type": "string"
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
"required": [
|
|
320
|
+
"name",
|
|
321
|
+
"trigger",
|
|
322
|
+
"steps"
|
|
323
|
+
],
|
|
324
|
+
"additionalProperties": false
|
|
325
|
+
},
|
|
326
|
+
"RoomProblem": {
|
|
327
|
+
"description": "A problem a room or page has drawing or reading what the person is working on: a face it cannot load, text it therefore does not draw, an asset that failed, something an import could not reproduce. Reported in a `problems` observation, so an assistant sees what the person sees in the banners.",
|
|
328
|
+
"type": "object",
|
|
329
|
+
"properties": {
|
|
330
|
+
"kind": {
|
|
331
|
+
"description": "`missing-font`, `font-error`, `unsupported-import`, `asset-failed`, `access-required`…",
|
|
332
|
+
"type": "string"
|
|
333
|
+
},
|
|
334
|
+
"message": {
|
|
335
|
+
"description": "The room's own words for it, as its banner says it.",
|
|
336
|
+
"type": "string"
|
|
337
|
+
},
|
|
338
|
+
"hides": {
|
|
339
|
+
"description": "Ids of the things not drawn because of it.",
|
|
340
|
+
"type": "array",
|
|
341
|
+
"items": {
|
|
342
|
+
"type": "string"
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
"resolve": {
|
|
346
|
+
"description": "How the person resolves it in the room: an action of this catalog, and the choices it offers.",
|
|
347
|
+
"type": "object",
|
|
348
|
+
"properties": {
|
|
349
|
+
"action": {
|
|
350
|
+
"type": "string"
|
|
351
|
+
},
|
|
352
|
+
"choices": {
|
|
353
|
+
"type": "array",
|
|
354
|
+
"items": {
|
|
355
|
+
"type": "object",
|
|
356
|
+
"additionalProperties": true
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
"required": [
|
|
361
|
+
"action"
|
|
362
|
+
],
|
|
363
|
+
"additionalProperties": false
|
|
364
|
+
},
|
|
365
|
+
"detail": {
|
|
366
|
+
"description": "Anything else that names the problem precisely (the face, the element).",
|
|
367
|
+
"type": "object",
|
|
368
|
+
"additionalProperties": true
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
"required": [
|
|
372
|
+
"kind",
|
|
373
|
+
"message"
|
|
374
|
+
],
|
|
375
|
+
"additionalProperties": false
|
|
376
|
+
},
|
|
377
|
+
"RoomResult": {
|
|
378
|
+
"description": "What running a catalog entry or a bound control did: its data, or why it could not be done, in words a person would read. `pending` says the work outlives the call: a job was started and is done only when its completion arrives (an action whose effect is `job` or `transaction`). Every binding's `run` returns what the consumer's callback returned (ADR-0226 §2.2 rule 3, #209), so a handler's `{ ok, pending: { jobId } }` reaches the runtime.",
|
|
379
|
+
"oneOf": [
|
|
380
|
+
{
|
|
381
|
+
"type": "object",
|
|
382
|
+
"properties": {
|
|
383
|
+
"ok": {
|
|
384
|
+
"const": true
|
|
385
|
+
},
|
|
386
|
+
"data": {
|
|
387
|
+
"type": "object",
|
|
388
|
+
"additionalProperties": true
|
|
389
|
+
},
|
|
390
|
+
"pending": {
|
|
391
|
+
"type": "object",
|
|
392
|
+
"properties": {
|
|
393
|
+
"jobId": {
|
|
394
|
+
"type": "string"
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
"required": [
|
|
398
|
+
"jobId"
|
|
399
|
+
],
|
|
400
|
+
"additionalProperties": false
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
"required": [
|
|
404
|
+
"ok"
|
|
405
|
+
],
|
|
406
|
+
"additionalProperties": false
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"type": "object",
|
|
410
|
+
"properties": {
|
|
411
|
+
"ok": {
|
|
412
|
+
"const": false
|
|
413
|
+
},
|
|
414
|
+
"code": {
|
|
415
|
+
"type": "string"
|
|
416
|
+
},
|
|
417
|
+
"message": {
|
|
418
|
+
"type": "string"
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
"required": [
|
|
422
|
+
"ok",
|
|
423
|
+
"code",
|
|
424
|
+
"message"
|
|
425
|
+
],
|
|
426
|
+
"additionalProperties": false
|
|
427
|
+
}
|
|
428
|
+
]
|
|
429
|
+
},
|
|
430
|
+
"AgentCatalogManifestEntry": {
|
|
431
|
+
"description": "Where a room package names its catalog, under `oui.agentCatalog` in its `package.json` (`closure.agentCatalog` is read during the transition). `hosts` are the exported components that mount the room (and register it); a page that renders one has the room's surface.\n\n```json\n\"oui\": { \"agentCatalog\": { \"path\": \"./dist/agent-catalog.json\", \"hosts\": [\"VectorStudioRoom\"] } }\n```",
|
|
432
|
+
"type": "object",
|
|
433
|
+
"properties": {
|
|
434
|
+
"path": {
|
|
435
|
+
"type": "string",
|
|
436
|
+
"minLength": 1
|
|
437
|
+
},
|
|
438
|
+
"hosts": {
|
|
439
|
+
"type": "array",
|
|
440
|
+
"items": {
|
|
441
|
+
"type": "string",
|
|
442
|
+
"minLength": 1
|
|
443
|
+
},
|
|
444
|
+
"minItems": 1,
|
|
445
|
+
"$comment": "ts: string[]"
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
"required": [
|
|
449
|
+
"path",
|
|
450
|
+
"hosts"
|
|
451
|
+
],
|
|
452
|
+
"additionalProperties": false
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.closurestudio.ai/oui/v1/tier2-mapping.json",
|
|
4
|
+
"title": "Tier2Mapping",
|
|
5
|
+
"description": "A tier 2 mapping (ADR-0226 §2.3): how an app binds the controls of a third-party design system it does not own (MUI, Mantine, shadcn/Radix). It is a declaration, not handler code: `oui generate` emits one module per mapping into `<out>/bound/`. Each wrapper accepts `agent`, calls `useAgentBinding` with the app's own callback, returns that callback's result (§2.2 rule 3), and renders the third-party component unchanged. The emitted module ships its own control table and is treated exactly like a tier 1 package. On an enforced page, importing a mapped component straight from the third-party package fails the build.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"$schema": {
|
|
9
|
+
"type": "string"
|
|
10
|
+
},
|
|
11
|
+
"package": {
|
|
12
|
+
"description": "The third-party package the controls are imported from (`@mantine/core`).",
|
|
13
|
+
"type": "string",
|
|
14
|
+
"minLength": 1
|
|
15
|
+
},
|
|
16
|
+
"controls": {
|
|
17
|
+
"description": "Each mapped export, by its export name in that package.",
|
|
18
|
+
"type": "object",
|
|
19
|
+
"minProperties": 1,
|
|
20
|
+
"propertyNames": {
|
|
21
|
+
"pattern": "^[A-Z][A-Za-z0-9]*$"
|
|
22
|
+
},
|
|
23
|
+
"additionalProperties": {
|
|
24
|
+
"$ref": "#/$defs/Tier2Control"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"required": [
|
|
29
|
+
"package",
|
|
30
|
+
"controls"
|
|
31
|
+
],
|
|
32
|
+
"additionalProperties": false,
|
|
33
|
+
"$defs": {
|
|
34
|
+
"ValueFrom": {
|
|
35
|
+
"description": "Where the new value is in the callback's arguments: `{ \"arg\": 0 }` for Mantine's `onChange(value)`, `{ \"arg\": 1 }` for MUI's `onChange(event, value)`, and `{ \"arg\": 0, \"path\": \"target.value\" }` for a native-style event. The wrapper builds those arguments when the assistant sets the value, and reads them back when the person does.",
|
|
36
|
+
"type": "object",
|
|
37
|
+
"properties": {
|
|
38
|
+
"arg": {
|
|
39
|
+
"description": "The argument's position.",
|
|
40
|
+
"type": "integer",
|
|
41
|
+
"minimum": 0
|
|
42
|
+
},
|
|
43
|
+
"path": {
|
|
44
|
+
"description": "A dotted path into that argument.",
|
|
45
|
+
"type": "string",
|
|
46
|
+
"pattern": "^[A-Za-z_$][A-Za-z0-9_$]*(\\.[A-Za-z_$][A-Za-z0-9_$]*)*$"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"required": [
|
|
50
|
+
"arg"
|
|
51
|
+
],
|
|
52
|
+
"additionalProperties": false
|
|
53
|
+
},
|
|
54
|
+
"Tier2Part": {
|
|
55
|
+
"description": "One part of a control exported under a namespace: the export path of that part (`Select.Root`, `Select.Item`, `Tabs.Tab`). A path is an export of the package, or one member of one (one dot at most).",
|
|
56
|
+
"type": "object",
|
|
57
|
+
"properties": {
|
|
58
|
+
"export": {
|
|
59
|
+
"description": "The part's export path: an export of the package, or one member of it, dotted (`Select.Item`).",
|
|
60
|
+
"type": "string",
|
|
61
|
+
"pattern": "^[A-Z][A-Za-z0-9]*(\\.[A-Z][A-Za-z0-9]*)?$"
|
|
62
|
+
},
|
|
63
|
+
"valueProp": {
|
|
64
|
+
"description": "On an item part: the prop that is the option's value.",
|
|
65
|
+
"type": "string",
|
|
66
|
+
"minLength": 1
|
|
67
|
+
},
|
|
68
|
+
"titleProps": {
|
|
69
|
+
"description": "On an item part: the props, in order, that give the option's title. `children` means its text.",
|
|
70
|
+
"type": "array",
|
|
71
|
+
"items": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"minLength": 1
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"required": [
|
|
78
|
+
"export"
|
|
79
|
+
],
|
|
80
|
+
"additionalProperties": false
|
|
81
|
+
},
|
|
82
|
+
"Tier2Control": {
|
|
83
|
+
"description": "One mapped control. The bound wrapper reports the component's `disabled` prop, so a control the page disables is not offered (a disabled job control is still followed until its job settles).",
|
|
84
|
+
"type": "object",
|
|
85
|
+
"properties": {
|
|
86
|
+
"kind": {
|
|
87
|
+
"$ref": "control-kind-registration.json#/$defs/AnyControlKind"
|
|
88
|
+
},
|
|
89
|
+
"callbacks": {
|
|
90
|
+
"description": "Props whose presence makes a use interactive. The first is the one a binding runs: for a value, with the arguments `valueFrom` describes; for a button or a dialog, with an event-shaped argument whose `isTrusted` is false.",
|
|
91
|
+
"type": "array",
|
|
92
|
+
"minItems": 1,
|
|
93
|
+
"items": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"minLength": 1
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"valueFrom": {
|
|
99
|
+
"description": "Required for every kind that takes a value (all but `button` and `dialog`).",
|
|
100
|
+
"$ref": "#/$defs/ValueFrom"
|
|
101
|
+
},
|
|
102
|
+
"controlled": {
|
|
103
|
+
"description": "The prop that shows the value. The generator reports every use of the control that does not pass it: there the handler would run, but the control would not show the new value.",
|
|
104
|
+
"type": "string",
|
|
105
|
+
"minLength": 1
|
|
106
|
+
},
|
|
107
|
+
"options": {
|
|
108
|
+
"description": "Where the options come from: the prop, and the keys of each option's value and title.",
|
|
109
|
+
"$ref": "control-table.json#/$defs/OptionsSource"
|
|
110
|
+
},
|
|
111
|
+
"titleProps": {
|
|
112
|
+
"description": "Props that give a default title, in order. `children` means the element's text.",
|
|
113
|
+
"type": "array",
|
|
114
|
+
"items": {
|
|
115
|
+
"type": "string",
|
|
116
|
+
"minLength": 1
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"schemaProps": {
|
|
120
|
+
"description": "Props the value schema is derived from, by `SchemaProps` key.",
|
|
121
|
+
"$ref": "control-table.json#/$defs/SchemaPropSources"
|
|
122
|
+
},
|
|
123
|
+
"defaults": {
|
|
124
|
+
"description": "What the schema props are when the app leaves them out, as the component defaults them.",
|
|
125
|
+
"$ref": "control-kind-registration.json#/$defs/SchemaProps"
|
|
126
|
+
},
|
|
127
|
+
"parts": {
|
|
128
|
+
"description": "A control exported under a namespace (Radix `Switch.Root`) or made of parts (Radix `Select.Root` / `Select.Item`, Mantine `Tabs` / `Tabs.Tab`): its `root`, which takes the callbacks, and, when the options are the items it renders, its `item`. The bound module keeps every other member of each namespace (`Select.Trigger`, `Tabs.List`).",
|
|
129
|
+
"type": "object",
|
|
130
|
+
"properties": {
|
|
131
|
+
"root": {
|
|
132
|
+
"$ref": "#/$defs/Tier2Part"
|
|
133
|
+
},
|
|
134
|
+
"item": {
|
|
135
|
+
"$ref": "#/$defs/Tier2Part"
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"required": [
|
|
139
|
+
"root"
|
|
140
|
+
],
|
|
141
|
+
"additionalProperties": false
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"required": [
|
|
145
|
+
"kind",
|
|
146
|
+
"callbacks"
|
|
147
|
+
],
|
|
148
|
+
"additionalProperties": false,
|
|
149
|
+
"allOf": [
|
|
150
|
+
{
|
|
151
|
+
"if": {
|
|
152
|
+
"properties": {
|
|
153
|
+
"kind": {
|
|
154
|
+
"not": {
|
|
155
|
+
"enum": [
|
|
156
|
+
"button",
|
|
157
|
+
"dialog"
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"then": {
|
|
164
|
+
"required": [
|
|
165
|
+
"valueFrom",
|
|
166
|
+
"controlled"
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"if": {
|
|
172
|
+
"required": [
|
|
173
|
+
"parts"
|
|
174
|
+
],
|
|
175
|
+
"properties": {
|
|
176
|
+
"parts": {
|
|
177
|
+
"type": "object",
|
|
178
|
+
"required": [
|
|
179
|
+
"item"
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
"then": {
|
|
185
|
+
"not": {
|
|
186
|
+
"required": [
|
|
187
|
+
"options"
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|