@hyphacommerce/app-blocks 0.0.0-stage → 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.
@@ -0,0 +1,402 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://hypha.dev/schemas/app-block/1.json",
4
+ "title": "Hypha app block, version 1",
5
+ "description": "A declarative UI tree an app answers for an admin target (design note 0029, §6.2). Hosts render it with their own components. Elements of a type this version doesn't know are allowed and render nothing, so newer elements don't break older hosts. Hosts also refuse trees nested deeper than 16 elements.",
6
+ "type": "object",
7
+ "required": ["version", "root"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "version": { "const": 1 },
11
+ "root": { "$ref": "#/$defs/element" }
12
+ },
13
+ "$defs": {
14
+ "text": { "type": "string", "maxLength": 2000 },
15
+ "label": { "type": "string", "minLength": 1, "maxLength": 200 },
16
+ "https": { "type": "string", "pattern": "^https://", "maxLength": 2048 },
17
+ "path": {
18
+ "description": "A path within the app's admin page, as the bridge's navigate takes it.",
19
+ "type": "string",
20
+ "pattern": "^/(?!/)",
21
+ "maxLength": 2048
22
+ },
23
+ "actionId": { "type": "string", "pattern": "^[a-z][a-z0-9_.-]{0,63}$" },
24
+ "gap": { "enum": [0, 1, 2, 3, 4] },
25
+ "tone": { "enum": ["neutral", "info", "success", "warning", "error"] },
26
+ "children": {
27
+ "type": "array",
28
+ "maxItems": 100,
29
+ "items": { "$ref": "#/$defs/element" }
30
+ },
31
+ "element": {
32
+ "type": "object",
33
+ "required": ["type"],
34
+ "properties": { "type": { "type": "string", "minLength": 1 } },
35
+ "allOf": [
36
+ {
37
+ "if": { "properties": { "type": { "const": "card" } } },
38
+ "then": { "$ref": "#/$defs/card" }
39
+ },
40
+ {
41
+ "if": { "properties": { "type": { "const": "stack" } } },
42
+ "then": { "$ref": "#/$defs/stack" }
43
+ },
44
+ {
45
+ "if": { "properties": { "type": { "const": "row" } } },
46
+ "then": { "$ref": "#/$defs/row" }
47
+ },
48
+ {
49
+ "if": { "properties": { "type": { "const": "text" } } },
50
+ "then": { "$ref": "#/$defs/textElement" }
51
+ },
52
+ {
53
+ "if": { "properties": { "type": { "const": "heading" } } },
54
+ "then": { "$ref": "#/$defs/heading" }
55
+ },
56
+ {
57
+ "if": { "properties": { "type": { "const": "badge" } } },
58
+ "then": { "$ref": "#/$defs/badge" }
59
+ },
60
+ {
61
+ "if": { "properties": { "type": { "const": "link" } } },
62
+ "then": { "$ref": "#/$defs/link" }
63
+ },
64
+ {
65
+ "if": { "properties": { "type": { "const": "button" } } },
66
+ "then": { "$ref": "#/$defs/button" }
67
+ },
68
+ {
69
+ "if": { "properties": { "type": { "const": "divider" } } },
70
+ "then": { "$ref": "#/$defs/divider" }
71
+ },
72
+ {
73
+ "if": { "properties": { "type": { "const": "image" } } },
74
+ "then": { "$ref": "#/$defs/image" }
75
+ },
76
+ {
77
+ "if": { "properties": { "type": { "const": "list" } } },
78
+ "then": { "$ref": "#/$defs/list" }
79
+ },
80
+ {
81
+ "if": { "properties": { "type": { "const": "table" } } },
82
+ "then": { "$ref": "#/$defs/table" }
83
+ },
84
+ {
85
+ "if": { "properties": { "type": { "const": "keyvalue" } } },
86
+ "then": { "$ref": "#/$defs/keyvalue" }
87
+ },
88
+ {
89
+ "if": { "properties": { "type": { "const": "form" } } },
90
+ "then": { "$ref": "#/$defs/form" }
91
+ },
92
+ {
93
+ "if": { "properties": { "type": { "const": "banner" } } },
94
+ "then": { "$ref": "#/$defs/banner" }
95
+ },
96
+ { "if": { "properties": { "type": { "const": "field" } } }, "then": false }
97
+ ]
98
+ },
99
+ "card": {
100
+ "type": "object",
101
+ "required": ["type", "children"],
102
+ "additionalProperties": false,
103
+ "properties": {
104
+ "type": { "const": "card" },
105
+ "title": { "$ref": "#/$defs/label" },
106
+ "children": { "$ref": "#/$defs/children" }
107
+ }
108
+ },
109
+ "stack": {
110
+ "description": "Children one above the other.",
111
+ "type": "object",
112
+ "required": ["type", "children"],
113
+ "additionalProperties": false,
114
+ "properties": {
115
+ "type": { "const": "stack" },
116
+ "gap": { "$ref": "#/$defs/gap" },
117
+ "children": { "$ref": "#/$defs/children" }
118
+ }
119
+ },
120
+ "row": {
121
+ "description": "Children side by side, wrapping on narrow screens.",
122
+ "type": "object",
123
+ "required": ["type", "children"],
124
+ "additionalProperties": false,
125
+ "properties": {
126
+ "type": { "const": "row" },
127
+ "gap": { "$ref": "#/$defs/gap" },
128
+ "align": { "enum": ["start", "center", "end", "between"] },
129
+ "children": { "$ref": "#/$defs/children" }
130
+ }
131
+ },
132
+ "textElement": {
133
+ "type": "object",
134
+ "required": ["type", "value"],
135
+ "additionalProperties": false,
136
+ "properties": {
137
+ "type": { "const": "text" },
138
+ "value": { "$ref": "#/$defs/text" },
139
+ "variant": { "enum": ["body", "supporting", "code"] },
140
+ "weight": { "enum": ["normal", "semibold"] }
141
+ }
142
+ },
143
+ "heading": {
144
+ "type": "object",
145
+ "required": ["type", "value"],
146
+ "additionalProperties": false,
147
+ "properties": {
148
+ "type": { "const": "heading" },
149
+ "value": { "$ref": "#/$defs/label" },
150
+ "level": { "enum": [2, 3, 4] }
151
+ }
152
+ },
153
+ "badge": {
154
+ "type": "object",
155
+ "required": ["type", "value"],
156
+ "additionalProperties": false,
157
+ "properties": {
158
+ "type": { "const": "badge" },
159
+ "value": { "type": "string", "minLength": 1, "maxLength": 50 },
160
+ "tone": { "$ref": "#/$defs/tone" }
161
+ }
162
+ },
163
+ "link": {
164
+ "description": "A link to an https URL; external links open in a new tab.",
165
+ "type": "object",
166
+ "required": ["type", "label", "href"],
167
+ "additionalProperties": false,
168
+ "properties": {
169
+ "type": { "const": "link" },
170
+ "label": { "$ref": "#/$defs/label" },
171
+ "href": { "$ref": "#/$defs/https" },
172
+ "external": { "type": "boolean" }
173
+ }
174
+ },
175
+ "button": {
176
+ "description": "Runs an action (design note 0029, §6.1) or navigates within the app's page: exactly one of action and navigate.",
177
+ "type": "object",
178
+ "required": ["type", "label"],
179
+ "additionalProperties": false,
180
+ "properties": {
181
+ "type": { "const": "button" },
182
+ "label": { "$ref": "#/$defs/label" },
183
+ "action": { "$ref": "#/$defs/actionId" },
184
+ "navigate": { "$ref": "#/$defs/path" },
185
+ "variant": { "enum": ["primary", "secondary", "destructive"] }
186
+ },
187
+ "oneOf": [{ "required": ["action"] }, { "required": ["navigate"] }]
188
+ },
189
+ "divider": {
190
+ "type": "object",
191
+ "required": ["type"],
192
+ "additionalProperties": false,
193
+ "properties": { "type": { "const": "divider" } }
194
+ },
195
+ "image": {
196
+ "type": "object",
197
+ "required": ["type", "src", "alt"],
198
+ "additionalProperties": false,
199
+ "properties": {
200
+ "type": { "const": "image" },
201
+ "src": { "$ref": "#/$defs/https" },
202
+ "alt": { "type": "string", "maxLength": 300 },
203
+ "width": { "type": "integer", "minimum": 1, "maximum": 2000 },
204
+ "height": { "type": "integer", "minimum": 1, "maximum": 2000 }
205
+ }
206
+ },
207
+ "list": {
208
+ "type": "object",
209
+ "required": ["type", "items"],
210
+ "additionalProperties": false,
211
+ "properties": {
212
+ "type": { "const": "list" },
213
+ "items": {
214
+ "type": "array",
215
+ "maxItems": 100,
216
+ "items": {
217
+ "type": "object",
218
+ "required": ["label"],
219
+ "additionalProperties": false,
220
+ "properties": {
221
+ "label": { "$ref": "#/$defs/label" },
222
+ "description": { "$ref": "#/$defs/text" }
223
+ }
224
+ }
225
+ }
226
+ }
227
+ },
228
+ "table": {
229
+ "type": "object",
230
+ "required": ["type", "columns", "rows"],
231
+ "additionalProperties": false,
232
+ "properties": {
233
+ "type": { "const": "table" },
234
+ "columns": {
235
+ "type": "array",
236
+ "minItems": 1,
237
+ "maxItems": 12,
238
+ "items": {
239
+ "type": "object",
240
+ "required": ["key", "header"],
241
+ "additionalProperties": false,
242
+ "properties": {
243
+ "key": { "type": "string", "pattern": "^[A-Za-z0-9_]{1,64}$" },
244
+ "header": { "$ref": "#/$defs/label" },
245
+ "align": { "enum": ["start", "end"] }
246
+ }
247
+ }
248
+ },
249
+ "rows": {
250
+ "type": "array",
251
+ "maxItems": 200,
252
+ "items": {
253
+ "type": "object",
254
+ "additionalProperties": { "type": ["string", "number", "null"] }
255
+ }
256
+ }
257
+ }
258
+ },
259
+ "keyvalue": {
260
+ "description": "Labelled values, like a details panel.",
261
+ "type": "object",
262
+ "required": ["type", "items"],
263
+ "additionalProperties": false,
264
+ "properties": {
265
+ "type": { "const": "keyvalue" },
266
+ "items": {
267
+ "type": "array",
268
+ "maxItems": 100,
269
+ "items": {
270
+ "type": "object",
271
+ "required": ["label", "value"],
272
+ "additionalProperties": false,
273
+ "properties": {
274
+ "label": { "$ref": "#/$defs/label" },
275
+ "value": { "$ref": "#/$defs/text" }
276
+ }
277
+ }
278
+ }
279
+ }
280
+ },
281
+ "form": {
282
+ "description": "Fields whose values are submitted to an action, as {name: value}.",
283
+ "type": "object",
284
+ "required": ["type", "action", "fields"],
285
+ "additionalProperties": false,
286
+ "properties": {
287
+ "type": { "const": "form" },
288
+ "action": { "$ref": "#/$defs/actionId" },
289
+ "submit_label": { "$ref": "#/$defs/label" },
290
+ "fields": {
291
+ "type": "array",
292
+ "minItems": 1,
293
+ "maxItems": 50,
294
+ "items": { "$ref": "#/$defs/field" }
295
+ }
296
+ }
297
+ },
298
+ "field": {
299
+ "type": "object",
300
+ "required": ["type", "input", "name", "label"],
301
+ "properties": {
302
+ "type": { "const": "field" },
303
+ "input": { "enum": ["text", "number", "select", "checkbox"] },
304
+ "name": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$" },
305
+ "label": { "$ref": "#/$defs/label" },
306
+ "description": { "$ref": "#/$defs/text" },
307
+ "required": { "type": "boolean" }
308
+ },
309
+ "allOf": [
310
+ {
311
+ "if": { "properties": { "input": { "const": "text" } } },
312
+ "then": {
313
+ "properties": {
314
+ "type": true,
315
+ "input": true,
316
+ "name": true,
317
+ "label": true,
318
+ "description": true,
319
+ "required": true,
320
+ "value": { "$ref": "#/$defs/text" },
321
+ "placeholder": { "$ref": "#/$defs/label" }
322
+ },
323
+ "additionalProperties": false
324
+ }
325
+ },
326
+ {
327
+ "if": { "properties": { "input": { "const": "number" } } },
328
+ "then": {
329
+ "properties": {
330
+ "type": true,
331
+ "input": true,
332
+ "name": true,
333
+ "label": true,
334
+ "description": true,
335
+ "required": true,
336
+ "value": { "type": "number" },
337
+ "min": { "type": "number" },
338
+ "max": { "type": "number" }
339
+ },
340
+ "additionalProperties": false
341
+ }
342
+ },
343
+ {
344
+ "if": { "properties": { "input": { "const": "select" } } },
345
+ "then": {
346
+ "required": ["options"],
347
+ "properties": {
348
+ "type": true,
349
+ "input": true,
350
+ "name": true,
351
+ "label": true,
352
+ "description": true,
353
+ "required": true,
354
+ "value": { "type": "string" },
355
+ "options": {
356
+ "type": "array",
357
+ "minItems": 1,
358
+ "maxItems": 100,
359
+ "items": {
360
+ "type": "object",
361
+ "required": ["value", "label"],
362
+ "additionalProperties": false,
363
+ "properties": {
364
+ "value": { "type": "string", "maxLength": 200 },
365
+ "label": { "$ref": "#/$defs/label" }
366
+ }
367
+ }
368
+ }
369
+ },
370
+ "additionalProperties": false
371
+ }
372
+ },
373
+ {
374
+ "if": { "properties": { "input": { "const": "checkbox" } } },
375
+ "then": {
376
+ "properties": {
377
+ "type": true,
378
+ "input": true,
379
+ "name": true,
380
+ "label": true,
381
+ "description": true,
382
+ "required": true,
383
+ "value": { "type": "boolean" }
384
+ },
385
+ "additionalProperties": false
386
+ }
387
+ }
388
+ ]
389
+ },
390
+ "banner": {
391
+ "type": "object",
392
+ "required": ["type", "tone", "title"],
393
+ "additionalProperties": false,
394
+ "properties": {
395
+ "type": { "const": "banner" },
396
+ "tone": { "enum": ["info", "success", "warning", "error"] },
397
+ "title": { "$ref": "#/$defs/label" },
398
+ "description": { "$ref": "#/$defs/text" }
399
+ }
400
+ }
401
+ }
402
+ }