1
1
# 📝 JSON Schema Form Element
2
2
3
+ [ ![ Published on webcomponents.org] ( https://img.shields.io/badge/webcomponents.org-published-blue.svg )] ( https://www.webcomponents.org/element/owner/my-element )
4
+
3
5
Effortless forms, with standards.
4
6
5
7
** Features** :
@@ -48,53 +50,58 @@ Jump to **implementations**:
48
50
<details >
49
51
<summary align =" center " ><strong >Table of Contents</strong ></summary >
50
52
51
- - [ 📝 JSON Schema Form Element] ( #json-schema-form-element )
52
- - [ Field types] ( #field-types )
53
- - [ Primitives] ( #primitives )
54
- - [ String] ( #string )
55
- - [ Number] ( #number )
56
- - [ Boolean] ( #boolean )
57
- - [ Enumeration] ( #enumeration )
58
- - [ Date] ( #date )
59
- - [ Object] ( #object )
60
- - [ Additional properties] ( #additional-properties )
61
- - [ Arrays] ( #arrays )
62
- - [ Basic] ( #basic )
63
- - [ Fixed] ( #fixed )
64
- - [ Nested] ( #nested )
65
- - [ Multiple choices (enums.)] ( #multiple-choices-enums )
66
- - [ Additional items] ( #additional-items )
67
- - [ Subschemas] ( #subschemas )
68
- - [ allOf] ( #allof )
69
- - [ oneOf] ( #oneof )
70
- - [ anyOf] ( #anyof )
71
- - [ Conditionals] ( #conditionals )
72
- - [ Dependencies] ( #dependencies )
73
- - [ If, then, else] ( #if-then-else )
74
- - [ Miscellaneous] ( #miscellaneous ) - [ References] ( #references ) - [ Recursivity] ( #recursivity ) - [ Nullable values] ( #nullable-values )
75
- - [ User Interface] ( #user-interface )
76
- - [ Schema] ( #schema )
77
- - [ Usage] ( #usage )
78
- - [ Installation] ( #installation )
79
- - [ Implementation] ( #implementation )
80
- - [ TypeScript (no framework)] ( #typescript-no-framework )
81
- - [ Astro (SSR)] ( #astro-ssr )
82
- - [ Lit] ( #lit )
83
- - [ Extended example] ( #extended-example )
84
- - [ Solid] ( #solid )
85
- - [ Vue] ( #vue )
86
- - [ Svelte] ( #svelte )
87
- - [ React] ( #react )
88
- - [ CSS] ( #css )
89
- - [ Component libraries] ( #component-libraries )
90
- - [ Shoelace] ( #shoelace )
91
- - [ Custom widgets] ( #custom-widgets )
92
- - [ Validation] ( #validation )
93
- - [ Schema massaging] ( #schema-massaging )
94
- - [ Custom Elements Manifests] ( #custom-elements-manifests )
95
- - [ Experimental features] ( #experimental-features )
96
- - [ Improvements] ( #improvements )
97
- - [ Acknowledgements] ( #acknowledgements )
53
+ - [ Field types] ( #field-types )
54
+ - [Primitives](#primitives)
55
+ - [String](#string)
56
+ - [Number](#number)
57
+ - [Boolean](#boolean)
58
+ - [Enumeration](#enumeration)
59
+ - [Date](#date)
60
+ - [Object](#object)
61
+ - [Additional properties](#additional-properties)
62
+ - [Arrays](#arrays)
63
+ - [Basic](#basic)
64
+ - [Fixed](#fixed)
65
+ - [Nested](#nested)
66
+ - [Multiple choices (enums.)](#multiple-choices-enums)
67
+ - [Additional items](#additional-items)
68
+ - [ Subschemas] ( #subschemas )
69
+ - [allOf](#allof)
70
+ - [oneOf](#oneof)
71
+ - [anyOf](#anyof)
72
+ - [ Conditionals] ( #conditionals )
73
+ - [Dependencies](#dependencies)
74
+ - [If, then, else](#if-then-else)
75
+ - [ Miscellaneous] ( #miscellaneous )
76
+ - [References](#references)
77
+ - [Recursivity](#recursivity)
78
+ - [Nullable values](#nullable-values)
79
+ - [ User Interface] ( #user-interface )
80
+ - [Schema](#schema)
81
+ - [ Usage] ( #usage )
82
+ - [Installation](#installation)
83
+ - [Implementation](#implementation)
84
+ - [All examples](#all-examples)
85
+ - [Pure HTML with CDN](#pure-html-with-cdn)
86
+ - [TypeScript (no framework)](#typescript-no-framework)
87
+ - [Astro (SSR)](#astro-ssr)
88
+ - [Lit](#lit)
89
+ - [Solid](#solid)
90
+ - [Vue](#vue)
91
+ - [Svelte](#svelte)
92
+ - [React](#react)
93
+ - [CSS](#css)
94
+ - [TypeScript](#typescript)
95
+ - [Support for each implementation](#support-for-each-implementation)
96
+ - [ Component libraries] ( #component-libraries )
97
+ - [Shoelace](#shoelace)
98
+ - [Custom widgets](#custom-widgets)
99
+ - [ Validation] ( #validation )
100
+ - [ Schema massaging] ( #schema-massaging )
101
+ - [ Custom Elements Manifests] ( #custom-elements-manifests )
102
+ - [ Experimental features] ( #experimental-features )
103
+ - [ Improvements] ( #improvements )
104
+ - [ Acknowledgements] ( #acknowledgements )
98
105
99
106
</details >
100
107
@@ -520,7 +527,9 @@ See also the [CSS section](#CSS).
520
527
### Implementation
521
528
522
529
> ** Note**
523
- > As the project is fresh, API is subject to changes
530
+ > This project is new, API is subject to changes
531
+
532
+ #### All examples
524
533
525
534
You can try the [ multi-frameworks examples] ( https://github.com/json-schema-form-element/examples ) like this:
526
535
@@ -533,107 +542,90 @@ npm i
533
542
npm run dev
534
543
```
535
544
545
+ #### Pure HTML with CDN
546
+
547
+ <!-- TODO: for WebComponents.org -->
548
+ <!--
549
+ ```
550
+ <custom-element-demo>
551
+ <template>
552
+ <link rel="import" href="my-element.html">
553
+ <link rel="import" href="../other-element/other-element.html">
554
+ <next-code-block></next-code-block>
555
+ </template>
556
+ </custom-element-demo>
557
+ ```
558
+ -->
559
+ <!-- ```html
560
+ <other-element></other-element>
561
+ <my-element></my-element>
562
+ ``` -->
563
+
564
+ See [ examples/src/pages/pure-html.html] ( https://github.com/json-schema-form-element/examples/blob/main/src/pages/pure-html.html )
565
+
566
+ -OR-
567
+
568
+ [ Open in ** CodePen.io** ] ( https://codepen.io/JulianCataldo/pen/KKbBepN?editors=1001 )
569
+
570
+ -OR-
571
+
572
+ [ Open in ** StackBlitz.com** ] ( https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fpages%2Fpure-html.html )
573
+
536
574
#### TypeScript (no framework)
537
575
538
576
See [ examples/src/components/TypeScriptOnly.ts] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/TypeScriptOnly.ts )
539
577
540
- ** TypeScript** inference: YES.
578
+ -OR-
579
+
580
+ [ Open in ** StackBlitz.com** ] ( https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FTypeScriptOnly.ts )
541
581
542
582
#### Astro (SSR)
543
583
544
584
See [ examples/src/components/AstroJs.astro] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/AstroJs.astro )
545
585
546
- ** TypeScript** inference: NO.
586
+ -OR-
587
+
588
+ [ Open in ** StackBlitz.com** ] ( https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FAstroJs.astro )
547
589
548
590
#### Lit
549
591
550
592
See [ examples/src/components/LitJs.ts] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/LitJs.ts )
551
593
552
- ** TypeScript ** inference: YES.
594
+ -OR-
553
595
554
- > ** Note**
555
- > Inside template literals, ** methods are type-checked** correctly,
556
- > but ** arguments are not inferred** automatically.
596
+ [ Open in ** StackBlitz.com** ] ( https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FLitJs.ts )
557
597
558
- ##### Extended example
598
+ #### Solid
559
599
560
- ``` ts
561
- // src/my-app.ts
562
- import { LitElement , html } from ' lit' ;
563
- import { customElement , state } from ' lit/decorators.js' ;
600
+ See [ examples/src/components/SolidJs.solid.tsx] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/SolidJs.solid.tsx )
564
601
565
- import type { JSONSchema7 } from ' json-schema' ;
566
- import { petSchema , type Pet } from ' @my-models/Pet.js' ;
602
+ -OR-
567
603
568
- import ' json-schema-form-element' ;
569
- import type { UiSchema } from ' json-schema-form-element' ;
604
+ [ Open in ** StackBlitz.com** ] ( https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FSolidJs.solid.tsx )
570
605
571
- // Shoelace namespaced custom properties (see notes on CSS below)
572
- import ' @shoelace-style/shoelace/dist/themes/light.css' ;
573
- import ' @shoelace-style/shoelace/dist/themes/dark.css' ;
606
+ #### Vue
574
607
575
- @customElement (' my-app' )
576
- class MyApp extends LitElement {
577
- @state () private schema: JSONSchema7 = { ... petSchema };
578
-
579
- @state () private data: Pet = {};
580
-
581
- @state () private uiSchema: UiSchema = {
582
- /* ... */
583
- };
584
-
585
- #form = () =>
586
- html ` <json-schema-form
587
- .schema=${this .schema }
588
- .uiSchema=${this .uiSchema }
589
- .data=${this .data }
590
- .onDataChange=${(newData : Pet ) => {
591
- this .data = data ;
592
- }}
593
- .onFormSubmit=${(newData : Pet , valid : boolean ) => {
594
- console .info (data , errors );
595
- }}
596
- ></json-schema-form> ` ;
597
-
598
- render() {
599
- const debug = {
600
- Schema: this .currentSchema ,
601
- ' UI schema' : this .currentUiSchema ,
602
- Data: this .currentData ,
603
- };
604
-
605
- return html `
606
- <h1>My App</h1>
607
-
608
- <main>${this .#form ()}</main>
609
-
610
- <footer>
611
- <pre>${JSON .stringify (debug , null , 2 )}</pre>
612
- </footer>
613
- ` ;
614
- }
615
- }
616
- ```
608
+ See [ examples/src/components/VueJs.vue] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/VueJs.vue )
617
609
618
- #### Solid
610
+ -OR-
619
611
620
- See [ examples/src/components/SolidJs.tsx ] ( https://github .com/json-schema-form-element/examples/blob/main/ src/components/SolidJs.tsx )
612
+ [ Open in ** StackBlitz.com ** ] ( https://stackblitz .com/github/ json-schema-form-element/examples?file= src%2Fcomponents%2FVueJs.vue )
621
613
622
- ** TypeScript ** inference: YES.
614
+ #### Svelte
623
615
624
- #### Vue
616
+ See [ examples/src/components/SvelteJs.svelte ] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/SvelteJs.svelte )
625
617
626
- See [ examples/src/components/VueJs.vue ] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/VueJs.vue )
618
+ -OR-
627
619
628
- ** TypeScript ** inference: NO.
620
+ [ Open in ** StackBlitz.com ** ] ( https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FSvelteJs.svelte )
629
621
630
- #### Svelte
622
+ #### React
631
623
632
- 🚧……🚧
624
+ See [ examples/src/components/ReactJs18.react.tsx ] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/ReactJs18.react.tsx )
633
625
634
- #### React
626
+ -OR-
635
627
636
- 🚧……🚧
628
+ [ Open in ** StackBlitz.com ** ] ( https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FReactJs18.react.tsx )
637
629
638
630
#### CSS
639
631
@@ -651,6 +643,36 @@ are injected globally.
651
643
652
644
<!-- TODO -->
653
645
646
+ ### TypeScript
647
+
648
+ #### Support for each implementation
649
+
650
+ | API | No framework | Astro (SSR) | Lit | Solid | Vue | React / Preact | Svelte |
651
+ | ------------------------- | ----------------- | ----------------- | ----------------- | -------------- | ------------ | -------------- | ----------------- |
652
+ | Declarative control | ✅ | ✅ | ✅ | ✅ via ` prop: ` | ✅ | ❌ | ❌ <sup >(4)</sup > |
653
+ | Declarative inference | ❌ <sup >(1)</sup > | ❌ <sup >(2)</sup > | ❌ <sup >(3)</sup > | ✅ via ` prop: ` | ❌ | ❌ | ❌ |
654
+ | Declarative type-checking | ❌ <sup >(1)</sup > | ❌ <sup >(2)</sup > | ✅ | ✅ via ` prop: ` | ❌ | ❌ | ❌ |
655
+ | Imperative control | ✅ via DOM | - | ✅ via ` ref ` | ✅ via ` ref ` | ✅ via ` ref ` | ✅ via ` ref ` | ✅ via ` use: ` |
656
+ | Imperative inference | ✅ via DOM | - | ✅ via ` ref ` | ✅ via ` ref ` | ✅ via ` ref ` | ✅ via ` ref ` | ✅ via ` use: ` |
657
+ | Imperative type-checking | ✅ via DOM | - | ✅ via ` ref ` | ✅ via ` ref ` | ✅ via ` ref ` | ✅ via ` ref ` | ✅ via ` use: ` |
658
+
659
+ 1 . HTML language servers can't support TypeScript obviously. But IDE can leverage Custom Element metadata.
660
+ 2 . Astro JSX namespace / LSP are not handling ` HTMLElementTagNameMap ` or Custom Element metadata, yet.
661
+ 3 . Template literals are preventing automatic properties inference, but at least, you can't assign wrong argument types without knowing it.
662
+ 4 . Svelte heuristics are not clear regarding _ attributes_ versus _ properties_ handling. Better be safe than sorry. Also the ` use: ` directive is neat.
663
+
664
+ There might be changes regarding support for Web Components accross various the various UI frameworks above.
665
+ Please file an issue if an info is wrong or missing.
666
+
667
+ Each implementation examples are trying to show off the most type-safe way to use JSFE, with the least trade-offs.
668
+
669
+ Using it more ** declaratively** or ** imperatively** is up to you, your framework ability and you coding style.
670
+ Bot usages are valid and can be mixed. Typically when you want to use the schema elsewhere in your app., or
671
+ when your callbacks are getting too beefy, you'll better extract them from templates.
672
+
673
+ Generally, imperative usage get perfect TypeScript support (you just handle the class), whereas declaratively, you'll have
674
+ to deal with various template languages limitations (this is an universal problem).
675
+
654
676
## Component libraries
655
677
656
678
### Shoelace
0 commit comments