11# 📝 JSON Schema Form Element
22
3+ [ ![ Published on webcomponents.org] ( https://img.shields.io/badge/webcomponents.org-published-blue.svg )] ( https://www.webcomponents.org/element/owner/my-element )
4+
35Effortless forms, with standards.
46
57** Features** :
@@ -48,53 +50,58 @@ Jump to **implementations**:
4850<details >
4951<summary align =" center " ><strong >Table of Contents</strong ></summary >
5052
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 )
98105
99106</details >
100107
@@ -520,7 +527,9 @@ See also the [CSS section](#CSS).
520527### Implementation
521528
522529> ** 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
524533
525534You can try the [ multi-frameworks examples] ( https://github.com/json-schema-form-element/examples ) like this:
526535
@@ -533,107 +542,90 @@ npm i
533542npm run dev
534543```
535544
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+
536574#### TypeScript (no framework)
537575
538576See [ examples/src/components/TypeScriptOnly.ts] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/TypeScriptOnly.ts )
539577
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 )
541581
542582#### Astro (SSR)
543583
544584See [ examples/src/components/AstroJs.astro] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/AstroJs.astro )
545585
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 )
547589
548590#### Lit
549591
550592See [ examples/src/components/LitJs.ts] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/LitJs.ts )
551593
552- ** TypeScript ** inference: YES.
594+ -OR-
553595
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 )
557597
558- ##### Extended example
598+ #### Solid
559599
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 )
564601
565- import type { JSONSchema7 } from ' json-schema' ;
566- import { petSchema , type Pet } from ' @my-models/Pet.js' ;
602+ -OR-
567603
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 )
570605
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
574607
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 )
617609
618- #### Solid
610+ -OR-
619611
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 )
621613
622- ** TypeScript ** inference: YES.
614+ #### Svelte
623615
624- #### Vue
616+ See [ examples/src/components/SvelteJs.svelte ] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/SvelteJs.svelte )
625617
626- See [ examples/src/components/VueJs.vue ] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/VueJs.vue )
618+ -OR-
627619
628- ** TypeScript ** inference: NO.
620+ [ Open in ** StackBlitz.com ** ] ( https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FSvelteJs.svelte )
629621
630- #### Svelte
622+ #### React
631623
632- 🚧……🚧
624+ See [ examples/src/components/ReactJs18.react.tsx ] ( https://github.com/json-schema-form-element/examples/blob/main/src/components/ReactJs18.react.tsx )
633625
634- #### React
626+ -OR-
635627
636- 🚧……🚧
628+ [ Open in ** StackBlitz.com ** ] ( https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FReactJs18.react.tsx )
637629
638630#### CSS
639631
@@ -651,6 +643,36 @@ are injected globally.
651643
652644<!-- TODO -->
653645
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+
654676## Component libraries
655677
656678### Shoelace
0 commit comments