@preset.nz/facets 0.1.2 → 0.1.3

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 CHANGED
@@ -185,6 +185,30 @@ the group, so it resets when the panel remounts.
185
185
 
186
186
  ---
187
187
 
188
+ ## JSON Schema
189
+
190
+ A schema for editors and agents is published at
191
+ `https://facets.preset.nz/schema/v0.1.json`, and ships in the package as
192
+ `@preset.nz/facets/schema/v0.1.json`. Point a JSON file at it:
193
+
194
+ ```json
195
+ {
196
+ "$schema": "https://facets.preset.nz/schema/v0.1.json",
197
+ "version": 1,
198
+ "groups": []
199
+ }
200
+ ```
201
+
202
+ Built-in kinds are checked strictly: a misspelt prop or a missing `path` is an
203
+ error. Any other kind passes as a custom kind, so a misspelt *kind* is not
204
+ caught here; the panel logs a warning and skips the field. `optionsProvider` is
205
+ code, so it has no JSON form.
206
+
207
+ One file covers every 0.1.x release. Patches may add kinds and props to it,
208
+ never remove or tighten them.
209
+
210
+ ---
211
+
188
212
  ## Read-only
189
213
 
190
214
  Omit `write`, or pass `readOnly`, and no change handler reaches the renderers.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preset.nz/facets",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Schema-as-data property/inspector panels for React: FieldDef schemas, a scope registry, an open field-renderer registry, and a generic PropertyPanel.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://facets.preset.nz",
@@ -11,10 +11,12 @@
11
11
  "type": "module",
12
12
  "sideEffects": false,
13
13
  "exports": {
14
- ".": "./src/index.ts"
14
+ ".": "./src/index.ts",
15
+ "./schema/v0.1.json": "./schema/v0.1.json"
15
16
  },
16
17
  "files": [
17
- "src"
18
+ "src",
19
+ "schema"
18
20
  ],
19
21
  "publishConfig": {
20
22
  "access": "public"
@@ -24,6 +26,7 @@
24
26
  },
25
27
  "devDependencies": {
26
28
  "@types/react": "^19",
29
+ "ajv": "^8.20.0",
27
30
  "typescript": "^5.8.3"
28
31
  }
29
32
  }
@@ -0,0 +1,801 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://facets.preset.nz/schema/v0.1.json",
4
+ "title": "@preset.nz/facets PropertySchema, 0.1",
5
+ "description": "An inspector panel as data: groups of rows of fields. Valid for every 0.1.x release; later 0.1 patches only add kinds and props. Playground: https://facets.preset.nz",
6
+ "type": "object",
7
+ "required": [
8
+ "version",
9
+ "groups"
10
+ ],
11
+ "additionalProperties": false,
12
+ "properties": {
13
+ "$schema": {
14
+ "type": "string",
15
+ "description": "This file's URL, for editors."
16
+ },
17
+ "version": {
18
+ "type": "number",
19
+ "description": "The host's own version of this schema. Bump it when the shape changes."
20
+ },
21
+ "groups": {
22
+ "type": "array",
23
+ "description": "Rendered top to bottom, with a rule between groups.",
24
+ "items": {
25
+ "$ref": "#/definitions/group"
26
+ }
27
+ }
28
+ },
29
+ "definitions": {
30
+ "group": {
31
+ "type": "object",
32
+ "required": [
33
+ "id",
34
+ "rows"
35
+ ],
36
+ "additionalProperties": false,
37
+ "properties": {
38
+ "id": {
39
+ "type": "string",
40
+ "description": "Unique within the schema."
41
+ },
42
+ "title": {
43
+ "type": "string",
44
+ "description": "The heading. Omit it to render the group without one."
45
+ },
46
+ "description": {
47
+ "type": "string",
48
+ "description": "A line under the title."
49
+ },
50
+ "collapsible": {
51
+ "type": "boolean",
52
+ "description": "Fold under the title. Needs a title."
53
+ },
54
+ "defaultCollapsed": {
55
+ "type": "boolean",
56
+ "description": "Start folded."
57
+ },
58
+ "rows": {
59
+ "type": "array",
60
+ "description": "A field is a full-width row; an array of fields is one row laid out as a grid (usually two).",
61
+ "items": {
62
+ "anyOf": [
63
+ {
64
+ "$ref": "#/definitions/field"
65
+ },
66
+ {
67
+ "type": "array",
68
+ "items": {
69
+ "$ref": "#/definitions/field"
70
+ }
71
+ }
72
+ ]
73
+ }
74
+ }
75
+ }
76
+ },
77
+ "disabledWhen": {
78
+ "type": "object",
79
+ "description": "Greys the field out depending on another field's value. Set one operator; if several are set, the first of equals, notEquals, in, notIn wins.",
80
+ "required": [
81
+ "path"
82
+ ],
83
+ "additionalProperties": false,
84
+ "properties": {
85
+ "path": {
86
+ "type": "string",
87
+ "description": "The field value to watch, by path."
88
+ },
89
+ "equals": {
90
+ "description": "Disabled when the value equals this."
91
+ },
92
+ "notEquals": {
93
+ "description": "Disabled unless the value equals this."
94
+ },
95
+ "in": {
96
+ "type": "array",
97
+ "description": "Disabled when the value is one of these."
98
+ },
99
+ "notIn": {
100
+ "type": "array",
101
+ "description": "Disabled unless the value is one of these."
102
+ }
103
+ }
104
+ },
105
+ "selectOption": {
106
+ "type": "object",
107
+ "required": [
108
+ "value",
109
+ "label"
110
+ ],
111
+ "additionalProperties": false,
112
+ "properties": {
113
+ "value": {
114
+ "type": "string",
115
+ "description": "Stored in the value record."
116
+ },
117
+ "label": {
118
+ "type": "string",
119
+ "description": "Shown to the user."
120
+ }
121
+ }
122
+ },
123
+ "vectorComponent": {
124
+ "type": "object",
125
+ "additionalProperties": false,
126
+ "properties": {
127
+ "label": {
128
+ "type": "string",
129
+ "description": "Shown above the slot."
130
+ },
131
+ "suffix": {
132
+ "type": "string",
133
+ "description": "Unit after the number, e.g. px or °."
134
+ },
135
+ "min": {
136
+ "type": "number",
137
+ "description": "Lower bound."
138
+ },
139
+ "max": {
140
+ "type": "number",
141
+ "description": "Upper bound."
142
+ },
143
+ "step": {
144
+ "type": "number",
145
+ "description": "Increment. Default 1."
146
+ }
147
+ }
148
+ },
149
+ "field": {
150
+ "type": "object",
151
+ "description": "One field. kind picks the renderer: a built-in kind is checked strictly; any other kind is a custom kind registered by the host, which may carry extra props.",
152
+ "required": [
153
+ "kind",
154
+ "id"
155
+ ],
156
+ "properties": {
157
+ "kind": {
158
+ "type": "string",
159
+ "description": "The renderer to use. Built in: text, textarea, number, slider, select, color, checkbox, file, vector, separator, label. Anything else must be registered by the host with registerFieldRenderer().",
160
+ "examples": [
161
+ "text",
162
+ "textarea",
163
+ "number",
164
+ "slider",
165
+ "select",
166
+ "color",
167
+ "checkbox",
168
+ "file",
169
+ "vector",
170
+ "separator",
171
+ "label"
172
+ ]
173
+ },
174
+ "id": {
175
+ "type": "string",
176
+ "description": "Unique within the schema. Keys the field in the panel."
177
+ }
178
+ },
179
+ "allOf": [
180
+ {
181
+ "if": {
182
+ "required": [
183
+ "kind"
184
+ ],
185
+ "properties": {
186
+ "kind": {
187
+ "const": "text"
188
+ }
189
+ }
190
+ },
191
+ "then": {
192
+ "$ref": "#/definitions/text"
193
+ }
194
+ },
195
+ {
196
+ "if": {
197
+ "required": [
198
+ "kind"
199
+ ],
200
+ "properties": {
201
+ "kind": {
202
+ "const": "textarea"
203
+ }
204
+ }
205
+ },
206
+ "then": {
207
+ "$ref": "#/definitions/textarea"
208
+ }
209
+ },
210
+ {
211
+ "if": {
212
+ "required": [
213
+ "kind"
214
+ ],
215
+ "properties": {
216
+ "kind": {
217
+ "const": "number"
218
+ }
219
+ }
220
+ },
221
+ "then": {
222
+ "$ref": "#/definitions/number"
223
+ }
224
+ },
225
+ {
226
+ "if": {
227
+ "required": [
228
+ "kind"
229
+ ],
230
+ "properties": {
231
+ "kind": {
232
+ "const": "slider"
233
+ }
234
+ }
235
+ },
236
+ "then": {
237
+ "$ref": "#/definitions/slider"
238
+ }
239
+ },
240
+ {
241
+ "if": {
242
+ "required": [
243
+ "kind"
244
+ ],
245
+ "properties": {
246
+ "kind": {
247
+ "const": "select"
248
+ }
249
+ }
250
+ },
251
+ "then": {
252
+ "$ref": "#/definitions/select"
253
+ }
254
+ },
255
+ {
256
+ "if": {
257
+ "required": [
258
+ "kind"
259
+ ],
260
+ "properties": {
261
+ "kind": {
262
+ "const": "color"
263
+ }
264
+ }
265
+ },
266
+ "then": {
267
+ "$ref": "#/definitions/color"
268
+ }
269
+ },
270
+ {
271
+ "if": {
272
+ "required": [
273
+ "kind"
274
+ ],
275
+ "properties": {
276
+ "kind": {
277
+ "const": "checkbox"
278
+ }
279
+ }
280
+ },
281
+ "then": {
282
+ "$ref": "#/definitions/checkbox"
283
+ }
284
+ },
285
+ {
286
+ "if": {
287
+ "required": [
288
+ "kind"
289
+ ],
290
+ "properties": {
291
+ "kind": {
292
+ "const": "file"
293
+ }
294
+ }
295
+ },
296
+ "then": {
297
+ "$ref": "#/definitions/file"
298
+ }
299
+ },
300
+ {
301
+ "if": {
302
+ "required": [
303
+ "kind"
304
+ ],
305
+ "properties": {
306
+ "kind": {
307
+ "const": "vector"
308
+ }
309
+ }
310
+ },
311
+ "then": {
312
+ "$ref": "#/definitions/vector"
313
+ }
314
+ },
315
+ {
316
+ "if": {
317
+ "required": [
318
+ "kind"
319
+ ],
320
+ "properties": {
321
+ "kind": {
322
+ "const": "separator"
323
+ }
324
+ }
325
+ },
326
+ "then": {
327
+ "$ref": "#/definitions/separator"
328
+ }
329
+ },
330
+ {
331
+ "if": {
332
+ "required": [
333
+ "kind"
334
+ ],
335
+ "properties": {
336
+ "kind": {
337
+ "const": "label"
338
+ }
339
+ }
340
+ },
341
+ "then": {
342
+ "$ref": "#/definitions/label"
343
+ }
344
+ },
345
+ {
346
+ "if": {
347
+ "required": [
348
+ "kind"
349
+ ],
350
+ "properties": {
351
+ "kind": {
352
+ "not": {
353
+ "enum": [
354
+ "text",
355
+ "textarea",
356
+ "number",
357
+ "slider",
358
+ "select",
359
+ "color",
360
+ "checkbox",
361
+ "file",
362
+ "vector",
363
+ "separator",
364
+ "label"
365
+ ]
366
+ }
367
+ }
368
+ }
369
+ },
370
+ "then": {
371
+ "$ref": "#/definitions/custom"
372
+ }
373
+ }
374
+ ]
375
+ },
376
+ "text": {
377
+ "type": "object",
378
+ "description": "A single line of text. Value: string.",
379
+ "required": [
380
+ "kind",
381
+ "id",
382
+ "path"
383
+ ],
384
+ "properties": {
385
+ "kind": {
386
+ "const": "text"
387
+ },
388
+ "id": {
389
+ "type": "string",
390
+ "description": "Unique within the schema. Keys the field in the panel."
391
+ },
392
+ "label": {
393
+ "type": "string",
394
+ "description": "Shown above the field. Defaults to id."
395
+ },
396
+ "path": {
397
+ "type": "string",
398
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
399
+ },
400
+ "disabledWhen": {
401
+ "$ref": "#/definitions/disabledWhen"
402
+ },
403
+ "placeholder": {
404
+ "type": "string",
405
+ "description": "Shown while empty."
406
+ }
407
+ },
408
+ "additionalProperties": false
409
+ },
410
+ "textarea": {
411
+ "type": "object",
412
+ "description": "Several lines of text. Value: string.",
413
+ "required": [
414
+ "kind",
415
+ "id",
416
+ "path"
417
+ ],
418
+ "properties": {
419
+ "kind": {
420
+ "const": "textarea"
421
+ },
422
+ "id": {
423
+ "type": "string",
424
+ "description": "Unique within the schema. Keys the field in the panel."
425
+ },
426
+ "label": {
427
+ "type": "string",
428
+ "description": "Shown above the field. Defaults to id."
429
+ },
430
+ "path": {
431
+ "type": "string",
432
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
433
+ },
434
+ "disabledWhen": {
435
+ "$ref": "#/definitions/disabledWhen"
436
+ },
437
+ "placeholder": {
438
+ "type": "string",
439
+ "description": "Shown while empty."
440
+ },
441
+ "rows": {
442
+ "type": "number",
443
+ "description": "Visible lines. Default 3."
444
+ }
445
+ },
446
+ "additionalProperties": false
447
+ },
448
+ "number": {
449
+ "type": "object",
450
+ "description": "A number typed into a box. Value: number.",
451
+ "required": [
452
+ "kind",
453
+ "id",
454
+ "path"
455
+ ],
456
+ "properties": {
457
+ "kind": {
458
+ "const": "number"
459
+ },
460
+ "id": {
461
+ "type": "string",
462
+ "description": "Unique within the schema. Keys the field in the panel."
463
+ },
464
+ "label": {
465
+ "type": "string",
466
+ "description": "Shown above the field. Defaults to id."
467
+ },
468
+ "path": {
469
+ "type": "string",
470
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
471
+ },
472
+ "disabledWhen": {
473
+ "$ref": "#/definitions/disabledWhen"
474
+ },
475
+ "min": {
476
+ "type": "number",
477
+ "description": "Lower bound."
478
+ },
479
+ "max": {
480
+ "type": "number",
481
+ "description": "Upper bound."
482
+ },
483
+ "step": {
484
+ "type": "number",
485
+ "description": "Increment. Default 1."
486
+ }
487
+ },
488
+ "additionalProperties": false
489
+ },
490
+ "slider": {
491
+ "type": "object",
492
+ "description": "A number dragged along a range. Value: number.",
493
+ "required": [
494
+ "kind",
495
+ "id",
496
+ "path"
497
+ ],
498
+ "properties": {
499
+ "kind": {
500
+ "const": "slider"
501
+ },
502
+ "id": {
503
+ "type": "string",
504
+ "description": "Unique within the schema. Keys the field in the panel."
505
+ },
506
+ "label": {
507
+ "type": "string",
508
+ "description": "Shown above the field. Defaults to id."
509
+ },
510
+ "path": {
511
+ "type": "string",
512
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
513
+ },
514
+ "disabledWhen": {
515
+ "$ref": "#/definitions/disabledWhen"
516
+ },
517
+ "min": {
518
+ "type": "number",
519
+ "description": "Lower bound."
520
+ },
521
+ "max": {
522
+ "type": "number",
523
+ "description": "Upper bound."
524
+ },
525
+ "step": {
526
+ "type": "number",
527
+ "description": "Increment. Default 1."
528
+ }
529
+ },
530
+ "additionalProperties": false
531
+ },
532
+ "select": {
533
+ "type": "object",
534
+ "description": "One choice from a list. Value: the chosen option's value (string). Options can also come from optionsProvider(ctx), a function, which is set in code and has no JSON form.",
535
+ "required": [
536
+ "kind",
537
+ "id",
538
+ "path"
539
+ ],
540
+ "properties": {
541
+ "kind": {
542
+ "const": "select"
543
+ },
544
+ "id": {
545
+ "type": "string",
546
+ "description": "Unique within the schema. Keys the field in the panel."
547
+ },
548
+ "label": {
549
+ "type": "string",
550
+ "description": "Shown above the field. Defaults to id."
551
+ },
552
+ "path": {
553
+ "type": "string",
554
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
555
+ },
556
+ "disabledWhen": {
557
+ "$ref": "#/definitions/disabledWhen"
558
+ },
559
+ "options": {
560
+ "type": "array",
561
+ "description": "The choices.",
562
+ "items": {
563
+ "$ref": "#/definitions/selectOption"
564
+ }
565
+ }
566
+ },
567
+ "additionalProperties": false
568
+ },
569
+ "color": {
570
+ "type": "object",
571
+ "description": "A colour as a hex string, e.g. \"#2b7c76\". Value: string.",
572
+ "required": [
573
+ "kind",
574
+ "id",
575
+ "path"
576
+ ],
577
+ "properties": {
578
+ "kind": {
579
+ "const": "color"
580
+ },
581
+ "id": {
582
+ "type": "string",
583
+ "description": "Unique within the schema. Keys the field in the panel."
584
+ },
585
+ "label": {
586
+ "type": "string",
587
+ "description": "Shown above the field. Defaults to id."
588
+ },
589
+ "path": {
590
+ "type": "string",
591
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
592
+ },
593
+ "disabledWhen": {
594
+ "$ref": "#/definitions/disabledWhen"
595
+ },
596
+ "presets": {
597
+ "type": "array",
598
+ "items": {
599
+ "type": "string"
600
+ },
601
+ "description": "Hex strings. Declared in 0.1; the built-in renderer does not draw them."
602
+ }
603
+ },
604
+ "additionalProperties": false
605
+ },
606
+ "checkbox": {
607
+ "type": "object",
608
+ "description": "On or off. Value: boolean.",
609
+ "required": [
610
+ "kind",
611
+ "id",
612
+ "path"
613
+ ],
614
+ "properties": {
615
+ "kind": {
616
+ "const": "checkbox"
617
+ },
618
+ "id": {
619
+ "type": "string",
620
+ "description": "Unique within the schema. Keys the field in the panel."
621
+ },
622
+ "label": {
623
+ "type": "string",
624
+ "description": "Shown above the field. Defaults to id."
625
+ },
626
+ "path": {
627
+ "type": "string",
628
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
629
+ },
630
+ "disabledWhen": {
631
+ "$ref": "#/definitions/disabledWhen"
632
+ }
633
+ },
634
+ "additionalProperties": false
635
+ },
636
+ "file": {
637
+ "type": "object",
638
+ "description": "Shows a file's name; always read-only. Value: { \"name\": string }.",
639
+ "required": [
640
+ "kind",
641
+ "id",
642
+ "path"
643
+ ],
644
+ "properties": {
645
+ "kind": {
646
+ "const": "file"
647
+ },
648
+ "id": {
649
+ "type": "string",
650
+ "description": "Unique within the schema. Keys the field in the panel."
651
+ },
652
+ "label": {
653
+ "type": "string",
654
+ "description": "Shown above the field. Defaults to id."
655
+ },
656
+ "path": {
657
+ "type": "string",
658
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
659
+ },
660
+ "disabledWhen": {
661
+ "$ref": "#/definitions/disabledWhen"
662
+ },
663
+ "accept": {
664
+ "type": "string",
665
+ "description": "File types, as on <input>. Declared in 0.1; the built-in renderer ignores it."
666
+ },
667
+ "helperText": {
668
+ "type": "string",
669
+ "description": "A hint. Declared in 0.1; the built-in renderer does not draw it."
670
+ }
671
+ },
672
+ "additionalProperties": false
673
+ },
674
+ "vector": {
675
+ "type": "object",
676
+ "description": "Several numbers in one row: position, size, RGB, LCh. Value: number[], one per component.",
677
+ "required": [
678
+ "kind",
679
+ "id",
680
+ "path",
681
+ "components"
682
+ ],
683
+ "properties": {
684
+ "kind": {
685
+ "const": "vector"
686
+ },
687
+ "id": {
688
+ "type": "string",
689
+ "description": "Unique within the schema. Keys the field in the panel."
690
+ },
691
+ "label": {
692
+ "type": "string",
693
+ "description": "Shown above the field. Defaults to id."
694
+ },
695
+ "path": {
696
+ "type": "string",
697
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
698
+ },
699
+ "disabledWhen": {
700
+ "$ref": "#/definitions/disabledWhen"
701
+ },
702
+ "components": {
703
+ "type": "array",
704
+ "description": "One entry per slot; sets the arity.",
705
+ "items": {
706
+ "$ref": "#/definitions/vectorComponent"
707
+ }
708
+ },
709
+ "integer": {
710
+ "type": "boolean",
711
+ "description": "Truncate to whole numbers."
712
+ },
713
+ "precision": {
714
+ "type": "number",
715
+ "description": "Decimals shown when read-only."
716
+ }
717
+ },
718
+ "additionalProperties": false
719
+ },
720
+ "separator": {
721
+ "type": "object",
722
+ "description": "A horizontal rule between rows, with label as an optional caption. Holds no value, so it has no path.",
723
+ "required": [
724
+ "kind",
725
+ "id"
726
+ ],
727
+ "properties": {
728
+ "kind": {
729
+ "const": "separator"
730
+ },
731
+ "id": {
732
+ "type": "string",
733
+ "description": "Unique within the schema. Keys the field in the panel."
734
+ },
735
+ "label": {
736
+ "type": "string",
737
+ "description": "Shown above the field. Defaults to id."
738
+ },
739
+ "disabledWhen": {
740
+ "$ref": "#/definitions/disabledWhen"
741
+ }
742
+ },
743
+ "additionalProperties": false
744
+ },
745
+ "label": {
746
+ "type": "object",
747
+ "description": "Static text: a hint, a note, a sub-heading. The text is label. Holds no value, so it has no path.",
748
+ "required": [
749
+ "kind",
750
+ "id",
751
+ "label"
752
+ ],
753
+ "properties": {
754
+ "kind": {
755
+ "const": "label"
756
+ },
757
+ "id": {
758
+ "type": "string",
759
+ "description": "Unique within the schema. Keys the field in the panel."
760
+ },
761
+ "label": {
762
+ "type": "string",
763
+ "description": "Shown above the field. Defaults to id."
764
+ },
765
+ "disabledWhen": {
766
+ "$ref": "#/definitions/disabledWhen"
767
+ }
768
+ },
769
+ "additionalProperties": false
770
+ },
771
+ "custom": {
772
+ "type": "object",
773
+ "description": "A custom kind. The host's renderer decides which extra props it reads.",
774
+ "required": [
775
+ "kind",
776
+ "id",
777
+ "path"
778
+ ],
779
+ "properties": {
780
+ "kind": {
781
+ "type": "string"
782
+ },
783
+ "id": {
784
+ "type": "string",
785
+ "description": "Unique within the schema. Keys the field in the panel."
786
+ },
787
+ "label": {
788
+ "type": "string",
789
+ "description": "Shown above the field. Defaults to id."
790
+ },
791
+ "path": {
792
+ "type": "string",
793
+ "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
794
+ },
795
+ "disabledWhen": {
796
+ "$ref": "#/definitions/disabledWhen"
797
+ }
798
+ }
799
+ }
800
+ }
801
+ }